From 4f0cb88f2c153157d0aee1760de61e6f621a9884 Mon Sep 17 00:00:00 2001 From: KINDNICK <68893236+KINDNICK@users.noreply.github.com> Date: Sun, 14 Sep 2025 00:24:42 +0900 Subject: [PATCH] =?UTF-8?q?Fix=20:=20=EC=9B=B9=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EB=94=94=EC=9E=90=EC=9D=B8=20=EA=B0=9C=ED=8E=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/settings.local.json | 11 + 404.html | 182 ++++ about.html | 194 ++++ components/footer.html | 10 + components/header.html | 25 + contact.html | 171 ++++ css/about.css | 318 +++++++ css/common.css | 655 ++++++++++++++ css/contact.css | 493 +++++++++++ css/gallery.css | 325 +++++++ css/main.css | 658 ++++++++++++++ css/portfolio.css | 450 ++++++++++ css/qna.css | 458 ++++++++++ css/services.css | 479 ++++++++++ gallery.html | 76 ++ index.html | 1615 ++++++++-------------------------- index_backup.html | 1303 +++++++++++++++++++++++++++ index_new.html | 164 ++++ js/common.js | 332 +++++++ js/contact.js | 372 ++++++++ js/gallery.js | 266 ++++++ js/main.js | 128 +++ js/portfolio.js | 478 ++++++++++ js/qna.js | 516 +++++++++++ js/services.js | 77 ++ naver-site-verification.html | 11 + portfolio.html | 325 +++++++ qna.html | 417 +++++++++ robots.txt | 27 +- services.html | 363 ++++++++ sitemap.xml | 45 +- 31 files changed, 9677 insertions(+), 1267 deletions(-) create mode 100644 .claude/settings.local.json create mode 100644 404.html create mode 100644 about.html create mode 100644 components/footer.html create mode 100644 components/header.html create mode 100644 contact.html create mode 100644 css/about.css create mode 100644 css/common.css create mode 100644 css/contact.css create mode 100644 css/gallery.css create mode 100644 css/main.css create mode 100644 css/portfolio.css create mode 100644 css/qna.css create mode 100644 css/services.css create mode 100644 gallery.html create mode 100644 index_backup.html create mode 100644 index_new.html create mode 100644 js/common.js create mode 100644 js/contact.js create mode 100644 js/gallery.js create mode 100644 js/main.js create mode 100644 js/portfolio.js create mode 100644 js/qna.js create mode 100644 js/services.js create mode 100644 naver-site-verification.html create mode 100644 portfolio.html create mode 100644 qna.html create mode 100644 services.html diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..f44ffc7 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,11 @@ +{ + "permissions": { + "allow": [ + "Bash(mkdir:*)", + "WebFetch(domain:www.youtube.com)", + "WebSearch" + ], + "deny": [], + "ask": [] + } +} \ No newline at end of file diff --git a/404.html b/404.html new file mode 100644 index 0000000..9e21d3f --- /dev/null +++ b/404.html @@ -0,0 +1,182 @@ + + + + + + 페이지를 찾을 수 없습니다 - 밍글 스튜디오 + + + + + + + + + + + +
+
404
+

페이지를 찾을 수 없습니다

+

+ 죄송합니다. 요청하신 페이지가 존재하지 않거나 이동되었을 수 있습니다.
+ 아래 링크를 통해 원하시는 정보를 찾아보세요. +

+ +
+ 🏠 홈으로 돌아가기 + 📞 문의하기 +
+ +
+ +
+ + +
+ + + + \ No newline at end of file diff --git a/about.html b/about.html new file mode 100644 index 0000000..94f7f5f --- /dev/null +++ b/about.html @@ -0,0 +1,194 @@ + + + + + + 회사소개 - 밍글 스튜디오 + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+
+
+
+

회사명

+

밍글 스튜디오 (Mingle Studio)

+
+
+

설립일

+

2025년 7월 15일

+
+
+

슬로건

+

"모두가 어우러진 즐거운 창작공간"

+
+
+

의미

+

Mingle Studio는 기술자와 크리에이터 그리고 시청자가 함께 어우러지는 버추얼 콘텐츠 제작 공간입니다. 최첨단 광학식 모션캡처 기술로 버추얼 캐릭터의 살아 숨쉬는 감정과 움직임을 담아 새로운 세대의 디지털 퍼포먼스를 실현합니다.

+
+
+
+ +
+
+

회사 소개

+

밍글 스튜디오는 창작자와 기술, 사람과 사람 사이의 '어우러짐'을 통해 새로운 콘텐츠를 만들어가는 모션 캡쳐 기반의 창작 공간입니다.

+

설립 이후, 누구나 편하게 사용 가능한 스튜디오 대관 서비스를 중심으로 버추얼 콘텐츠 제작 환경을 제공합니다.

+
+ +
+

비전 & 미션

+
+
+

🎯 비전

+

모든 창작자가 기술적 제약 없이 상상을 현실로 만들 수 있는 창작 생태계 구축

+
+
+

🚀 미션

+

최첨단 모션캡쳐 기술을 통해 창작자들의 아이디어를 생생한 콘텐츠로 변환하고, 새로운 디지털 경험을 제공

+
+
+
+ +
+

연혁

+
+
+
2025년 7월 15일
+
+

밍글 스튜디오 설립

+

밍글 스튜디오 회사 설립

+
+
+
+
2025년 8월 1일
+
+

스튜디오 오픈

+

OptiTrack 시스템 구축 완료 및 대관 서비스 시작

+
+
+
+
+
+
+
+ + +
+
+
+

Our Team

+

각 분야의 전문가들이 함께 협업하며 콘텐츠 제작을 지원합니다

+
+ +
+
+
👤
+

김희진

+

JAYJAY

+

대표 / 3D 아티스트

+

배경/리소스 제작, 인사 및 프로젝트 관리

+
+ +
+
👤
+

김광진

+

KINDNICK

+

CTO / 테크니컬 디렉터

+

스튜디오 전체 기술 운영, 모션캡쳐 장비 관리, 음향 시스템, 엔진 프로그래밍

+
+ +
+
👤
+

이승민

+

YAMO

+

CCO / 콘텐츠 디렉터

+

캡쳐 디렉팅, 배우 모션 클린업, 카메라 무빙, 퍼포먼스 연출

+
+
+
+
+ + +
+
+
+

Core Values

+

밍글 스튜디오가 추구하는 핵심 가치

+
+ +
+
+
🤝
+

협업

+

기술자와 창작자가 함께 만드는 시너지

+
+
+
💡
+

혁신

+

최신 기술로 새로운 창작의 가능성 제시

+
+
+
🎨
+

창의성

+

상상을 현실로 만드는 창의적 솔루션

+
+
+
+

품질

+

최고 수준의 모션캡쳐 퀄리티 추구

+
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/components/footer.html b/components/footer.html new file mode 100644 index 0000000..a0662b8 --- /dev/null +++ b/components/footer.html @@ -0,0 +1,10 @@ + + \ No newline at end of file diff --git a/components/header.html b/components/header.html new file mode 100644 index 0000000..6526736 --- /dev/null +++ b/components/header.html @@ -0,0 +1,25 @@ + + \ No newline at end of file diff --git a/contact.html b/contact.html new file mode 100644 index 0000000..2bdcb85 --- /dev/null +++ b/contact.html @@ -0,0 +1,171 @@ + + + + + + 문의하기 - 밍글 스튜디오 + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+
+
+
📞
+

전화 문의

+

24시간 가능

+ 010-9288-9190 +
+ +
+
✉️
+

이메일 문의

+

24시간 접수 가능

+ minglestudio.mocap@gmail.com +
+ +
+
📍
+

스튜디오 방문

+

사전 예약 필수

+ 위치 보기 +
+
+
+
+ + + +
+
+
+

스튜디오 위치

+
+ +
+
+
+

📍 주소

+

(21330) 인천광역시 부평구 주부토로 236
+ 인천테크노밸리 A동 B105호

+ +

🚇 지하철

+
    +
  • 인천 7호선 갈산역 하차 → 도보 약 7분
  • +
+ +

🚌 버스

+
    +
  • 갈산시장·갈산도서관 정류장 이용
  • +
  • 4번, 526번, 555번 버스
  • +
+ +

🚗 주차

+

기본 2시간 무료, 건물 내 시설 이용시 최대 4시간 무료

+ +

🕐 운영시간

+
    +
  • 24시간 영업
  • +
  • 연중무휴
  • +
+
+ +
+
+ +
+ + +
+
+
+
+
+ + +
+
+

예약 및 문의

+

간편한 온라인 예약 또는 자주 묻는 질문을 확인해보세요

+ +
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/css/about.css b/css/about.css new file mode 100644 index 0000000..c26b020 --- /dev/null +++ b/css/about.css @@ -0,0 +1,318 @@ +/* ======================================== + About 페이지 전용 스타일 + ======================================== */ + +/* 페이지 헤더 */ +.page-header { + background: linear-gradient(135deg, var(--primary-color), #ff6600); + color: var(--bg-white); + padding: var(--spacing-3xl) 0; + text-align: center; +} + +.page-header h1 { + font-size: var(--font-5xl); + margin-bottom: var(--spacing-md); +} + +.page-header p { + font-size: var(--font-xl); + opacity: 0.95; +} + +/* 회사 정보 그리드 */ +.company-info { + margin-bottom: var(--spacing-3xl); +} + +.info-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: var(--spacing-xl); + background: var(--bg-light); + padding: var(--spacing-2xl); + border-radius: var(--border-radius); +} + +.info-item h3 { + color: var(--primary-color); + font-size: var(--font-sm); + text-transform: uppercase; + letter-spacing: 1px; + margin-bottom: var(--spacing-sm); +} + +.info-item p { + font-size: var(--font-lg); + color: var(--text-primary); + font-weight: 500; +} + +.info-item.full-width { + grid-column: 1 / -1; +} + +.info-item.full-width p { + line-height: 1.8; + color: var(--text-secondary); + font-weight: 400; +} + +/* About 콘텐츠 */ +.about-content { + display: flex; + flex-direction: column; + gap: var(--spacing-2xl); +} + +.about-content .card { + padding: var(--spacing-2xl); +} + +.about-content h2 { + color: var(--text-primary); + margin-bottom: var(--spacing-lg); + font-size: var(--font-3xl); +} + +.about-content p { + color: var(--text-secondary); + line-height: 1.8; + margin-bottom: var(--spacing-md); +} + +.about-content p:last-child { + margin-bottom: 0; +} + +/* 비전 & 미션 */ +.vision-mission { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: var(--spacing-xl); + margin-top: var(--spacing-lg); +} + +.vm-item { + padding: var(--spacing-xl); + background: var(--bg-light); + border-radius: var(--border-radius); + border-left: 4px solid var(--primary-color); +} + +.vm-item h3 { + font-size: var(--font-xl); + margin-bottom: var(--spacing-md); + color: var(--text-primary); +} + +.vm-item p { + line-height: 1.6; +} + +/* 타임라인 */ +.timeline { + position: relative; + padding: var(--spacing-xl) 0; +} + +.timeline::before { + content: ''; + position: absolute; + left: 30px; + top: 0; + bottom: 0; + width: 2px; + background: var(--primary-color); +} + +.timeline-item { + position: relative; + padding-left: 80px; + margin-bottom: var(--spacing-2xl); +} + +.timeline-item::before { + content: ''; + position: absolute; + left: 22px; + top: 5px; + width: 16px; + height: 16px; + border-radius: 50%; + background: var(--primary-color); + border: 4px solid var(--bg-white); + box-shadow: 0 0 0 2px var(--primary-color); +} + +.timeline-date { + position: absolute; + left: 60px; + top: 0; + color: var(--primary-color); + font-weight: 600; + font-size: var(--font-sm); + white-space: nowrap; +} + +.timeline-content { + background: var(--bg-light); + padding: var(--spacing-lg); + border-radius: var(--border-radius); + margin-left: var(--spacing-xl); +} + +.timeline-content h4 { + color: var(--text-primary); + margin-bottom: var(--spacing-sm); +} + +.timeline-content p { + color: var(--text-secondary); + margin: 0; +} + +/* 팀 섹션 */ +.team-section { + background: var(--bg-light); +} + +.team-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: var(--spacing-xl); + margin-top: var(--spacing-2xl); +} + +.team-card { + background: var(--bg-white); + padding: var(--spacing-2xl); + border-radius: var(--border-radius); + text-align: center; + transition: var(--transition); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08); +} + +.team-card:hover { + transform: translateY(-10px); + box-shadow: 0 15px 35px rgba(0, 0, 0, 0.15); +} + +.team-avatar { + width: 100px; + height: 100px; + margin: 0 auto var(--spacing-lg); + background: linear-gradient(135deg, var(--primary-color), #ff6600); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 3rem; +} + +.team-card h3 { + font-size: var(--font-2xl); + color: var(--text-primary); + margin-bottom: var(--spacing-xs); +} + +.team-nickname { + color: var(--primary-color); + font-weight: 500; + margin-bottom: var(--spacing-sm); +} + +.team-role { + color: var(--text-secondary); + font-weight: 600; + margin-bottom: var(--spacing-md); +} + +.team-desc { + color: var(--text-secondary); + line-height: 1.6; + font-size: var(--font-sm); +} + +/* 핵심 가치 섹션 */ +.values-section { + padding: var(--spacing-3xl) 0; +} + +.values-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: var(--spacing-xl); + margin-top: var(--spacing-2xl); +} + +.value-item { + text-align: center; + padding: var(--spacing-xl); + background: var(--bg-white); + border-radius: var(--border-radius); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08); + transition: var(--transition); +} + +.value-item:hover { + transform: translateY(-5px); + box-shadow: 0 10px 25px rgba(0, 0, 0, 0.12); +} + +.value-icon { + font-size: 3rem; + margin-bottom: var(--spacing-md); +} + +.value-item h3 { + color: var(--text-primary); + margin-bottom: var(--spacing-sm); + font-size: var(--font-xl); +} + +.value-item p { + color: var(--text-secondary); + line-height: 1.6; +} + +/* 반응형 디자인 */ +@media (max-width: 768px) { + .page-header h1 { + font-size: var(--font-3xl); + } + + .page-header p { + font-size: var(--font-base); + } + + .timeline::before { + left: 20px; + } + + .timeline-item { + padding-left: 60px; + } + + .timeline-item::before { + left: 12px; + } + + .timeline-date { + position: relative; + left: 0; + margin-bottom: var(--spacing-sm); + } + + .timeline-content { + margin-left: 0; + } + + .team-grid { + grid-template-columns: 1fr; + } + + .values-grid { + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + } +} \ No newline at end of file diff --git a/css/common.css b/css/common.css new file mode 100644 index 0000000..2a663c1 --- /dev/null +++ b/css/common.css @@ -0,0 +1,655 @@ +/* ======================================== + CSS 변수 정의 - 모션캡쳐/버튜버 테마 + ======================================== */ +:root { + /* 메인 색상 - 오렌지 계열 */ + --primary-color: #ff8800; + --primary-hover: #ff6600; + --secondary-color: #ff9933; + --secondary-hover: #ff7700; + --accent-color: #ffaa44; + + /* 네온/하이테크 색상 - 오렌지 계열 */ + --neon-purple: #ff6600; + --neon-blue: #ff8800; + --neon-pink: #ff9933; + --gradient-main: linear-gradient(135deg, #ff8800 0%, #ff6600 100%); + --gradient-warm: linear-gradient(120deg, #fff7ed 60%, #ffe0b2 100%); + + /* 텍스트 색상 */ + --text-primary: #222222; + --text-secondary: #666666; + --text-light: #999999; + --text-white: #ffffff; + + /* 배경 색상 */ + --bg-white: #ffffff; + --bg-light: #f8fafc; + --bg-gray: #f3f4f6; + --bg-dark: #1a1a2e; + + /* 간격 시스템 */ + --spacing-xs: 0.25rem; + --spacing-sm: 0.5rem; + --spacing-md: 1rem; + --spacing-lg: 1.5rem; + --spacing-xl: 2rem; + --spacing-2xl: 3rem; + --spacing-3xl: 5rem; + + /* 폰트 크기 */ + --font-xs: 0.75rem; + --font-sm: 0.875rem; + --font-base: 1rem; + --font-lg: 1.1rem; + --font-xl: 1.25rem; + --font-2xl: 1.5rem; + --font-3xl: 2rem; + --font-4xl: 2.5rem; + --font-5xl: 3.5rem; + + /* 기타 */ + --border-radius: 15px; + --border-radius-sm: 8px; + --border-radius-full: 50px; + --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + --box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); + --box-shadow-lg: 0 20px 50px rgba(0, 0, 0, 0.15); + --navbar-height: 70px; +} + +/* ======================================== + 기본 스타일 리셋 + ======================================== */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body { + font-family: 'Pretendard', 'Noto Sans KR', sans-serif; + line-height: 1.6; + color: var(--text-primary); + background-color: var(--bg-light); + overflow-x: hidden; + padding-top: var(--navbar-height); +} + +/* ======================================== + 공통 레이아웃 + ======================================== */ +.container { + max-width: 1100px; + margin: 0 auto; + padding: 0 var(--spacing-lg); +} + +.section { + padding: var(--spacing-3xl) 0; +} + +.section-header { + text-align: center; + margin-bottom: var(--spacing-2xl); +} + +.section-header h1, +.section-header h2 { + font-size: var(--font-4xl); + font-weight: 700; + margin-bottom: var(--spacing-md); + color: var(--text-primary); + position: relative; + display: inline-block; +} + +.section-header h2::after { + content: ''; + position: absolute; + bottom: -10px; + left: 50%; + transform: translateX(-50%); + width: 60px; + height: 3px; + background: var(--gradient-main); + border-radius: 2px; +} + +.section-header p { + font-size: var(--font-lg); + color: var(--text-secondary); + max-width: 800px; + margin: 0 auto; +} + +/* ======================================== + 네비게이션 바 + ======================================== */ +.navbar { + position: fixed; + top: 0; + width: 100%; + height: var(--navbar-height); + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(10px); + z-index: 1000; + padding: var(--spacing-md) 0; + transition: var(--transition); + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05); +} + +.nav-container { + max-width: 1200px; + margin: 0 auto; + padding: 0 var(--spacing-lg); + display: flex; + justify-content: space-between; + align-items: center; +} + +.nav-logo { + display: flex; + align-items: center; + gap: var(--spacing-sm); +} + +.nav-logo a { + display: flex; + align-items: center; + gap: var(--spacing-sm); + text-decoration: none; +} + +.nav-logo img { + height: 40px; + width: auto; +} + +.nav-logo span { + font-size: 1.3rem; + font-weight: 700; + color: var(--primary-color); + white-space: nowrap; + letter-spacing: 0.01em; +} + +.nav-menu { + display: flex; + list-style: none; + gap: var(--spacing-xl); +} + +.nav-link { + color: var(--text-primary); + text-decoration: none; + font-weight: 500; + padding: var(--spacing-sm) var(--spacing-md); + border-radius: var(--border-radius-full); + transition: var(--transition); + position: relative; +} + +.nav-link::after { + content: ''; + position: absolute; + bottom: 0; + left: 50%; + width: 0; + height: 2px; + background: var(--primary-color); + transition: var(--transition); + transform: translateX(-50%); +} + +.nav-link:hover::after { + width: 80%; +} + +.nav-link:hover { + color: var(--primary-color); +} + +.nav-link.active { + background: linear-gradient(135deg, var(--primary-color), var(--primary-hover)); + color: var(--text-white); +} + +.hamburger { + display: none; + flex-direction: column; + cursor: pointer; +} + +.hamburger span { + width: 25px; + height: 3px; + background-color: var(--text-primary); + margin: 3px 0; + transition: var(--transition); +} + +.hamburger.active span:nth-child(1) { + transform: rotate(45deg) translate(5px, 5px); +} + +.hamburger.active span:nth-child(2) { + opacity: 0; +} + +.hamburger.active span:nth-child(3) { + transform: rotate(-45deg) translate(7px, -6px); +} + +/* ======================================== + 푸터 + ======================================== */ +.footer { + background-color: var(--text-primary); + color: var(--bg-white); + padding: var(--spacing-2xl) 0 var(--spacing-xl); + margin-top: var(--spacing-3xl); +} + +.footer-content { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: var(--spacing-2xl); + margin-bottom: var(--spacing-2xl); +} + +.footer-section h3, +.footer-section h4 { + margin-bottom: var(--spacing-md); + color: var(--bg-white); +} + +.footer-section ul { + list-style: none; +} + +.footer-section ul li { + margin-bottom: var(--spacing-sm); +} + +.footer-section a { + color: rgba(255, 255, 255, 0.8); + text-decoration: none; + transition: var(--transition); +} + +.footer-section a:hover { + color: var(--primary-color); +} + +.social-links { + display: flex; + gap: var(--spacing-md); +} + +.footer-bottom { + text-align: center; + padding-top: var(--spacing-xl); + border-top: 1px solid rgba(255, 255, 255, 0.1); + color: rgba(255, 255, 255, 0.6); +} + +/* ======================================== + 버튼 스타일 + ======================================== */ +.btn { + display: inline-block; + padding: var(--spacing-md) var(--spacing-xl); + font-size: var(--font-base); + font-weight: 600; + text-decoration: none; + border-radius: var(--border-radius-full); + transition: var(--transition); + cursor: pointer; + border: none; + outline: none; + position: relative; + overflow: hidden; +} + +.btn::before { + content: ''; + position: absolute; + top: 50%; + left: 50%; + width: 0; + height: 0; + border-radius: 50%; + background: rgba(255, 255, 255, 0.3); + transform: translate(-50%, -50%); + transition: width 0.6s, height 0.6s; +} + +.btn:hover::before { + width: 300px; + height: 300px; +} + +.btn-primary { + background: linear-gradient(135deg, var(--primary-color), var(--primary-hover)); + color: var(--text-white); + box-shadow: 0 4px 15px rgba(255, 136, 0, 0.3); +} + +.btn-primary:hover { + transform: translateY(-3px); + box-shadow: 0 8px 25px rgba(255, 136, 0, 0.4); +} + +.btn-secondary { + background: linear-gradient(135deg, var(--primary-color), var(--primary-hover)); + color: var(--text-white); + box-shadow: 0 4px 15px rgba(255, 136, 0, 0.3); +} + +.btn-secondary:hover { + transform: translateY(-3px); + box-shadow: 0 8px 25px rgba(255, 136, 0, 0.4); +} + +.btn-outline { + background-color: transparent; + border: 2px solid var(--primary-color); + color: var(--primary-color); +} + +.btn-outline:hover { + background-color: var(--primary-color); + color: var(--bg-white); +} + +/* ======================================== + 카드 스타일 + ======================================== */ +.card { + background-color: var(--bg-white); + border-radius: var(--border-radius); + padding: var(--spacing-xl); + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); + transition: var(--transition); + position: relative; + overflow: hidden; +} + +.card::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255, 136, 0, 0.05), transparent); + transition: left 0.5s; +} + +.card:hover::before { + left: 100%; +} + +.card:hover { + transform: translateY(-8px) scale(1.02); + box-shadow: 0 15px 40px rgba(0, 0, 0, 0.12); +} + +/* ======================================== + 그리드 시스템 + ======================================== */ +.grid { + display: grid; + gap: var(--spacing-xl); +} + +.grid-2 { + grid-template-columns: repeat(auto-fit, minmax(500px, 1fr)); +} + +.grid-3 { + grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); +} + +.grid-4 { + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); +} + +/* ======================================== + 유틸리티 클래스 + ======================================== */ +.text-center { + text-align: center; +} + +.text-primary { + color: var(--primary-color); +} + +.bg-light { + background-color: var(--bg-light); +} + +.mt-1 { margin-top: var(--spacing-sm); } +.mt-2 { margin-top: var(--spacing-md); } +.mt-3 { margin-top: var(--spacing-lg); } +.mt-4 { margin-top: var(--spacing-xl); } +.mt-5 { margin-top: var(--spacing-2xl); } + +.mb-1 { margin-bottom: var(--spacing-sm); } +.mb-2 { margin-bottom: var(--spacing-md); } +.mb-3 { margin-bottom: var(--spacing-lg); } +.mb-4 { margin-bottom: var(--spacing-xl); } +.mb-5 { margin-bottom: var(--spacing-2xl); } + +/* ======================================== + 브레드크럼 네비게이션 + ======================================== */ +.breadcrumb { + padding: var(--spacing-md) 0; + background: var(--bg-light); + border-bottom: 1px solid rgba(0, 0, 0, 0.05); +} + +.breadcrumb-list { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: var(--spacing-xs); + list-style: none; + margin: 0; + padding: 0; + font-size: var(--font-sm); +} + +.breadcrumb-item { + display: flex; + align-items: center; +} + +.breadcrumb-item:not(:last-child)::after { + content: '›'; + margin: 0 var(--spacing-xs); + color: var(--text-secondary); + font-weight: 600; +} + +.breadcrumb-link { + color: var(--text-secondary); + text-decoration: none; + transition: var(--transition); + padding: var(--spacing-xs) var(--spacing-sm); + border-radius: var(--border-radius); +} + +.breadcrumb-link:hover { + color: var(--primary-color); + background: rgba(255, 136, 0, 0.1); +} + +.breadcrumb-current { + color: var(--text-primary); + font-weight: 600; + padding: var(--spacing-xs) var(--spacing-sm); +} + +.breadcrumb-home { + font-size: 1.1em; +} + +/* ======================================== + 로딩 상태 + ======================================== */ +.loading-overlay { + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + background: rgba(255, 255, 255, 0.95); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + z-index: 9999; + transition: opacity 0.3s ease; +} + +.loading-spinner { + width: 50px; + height: 50px; + border: 4px solid #f3f4f6; + border-top: 4px solid var(--primary-color); + border-radius: 50%; + animation: spin 1s linear infinite; + margin-bottom: var(--spacing-md); +} + +.loading-text { + color: var(--text-secondary); + font-size: var(--font-base); + font-weight: 500; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +.component-loading { + display: flex; + justify-content: center; + align-items: center; + padding: var(--spacing-2xl); + background: var(--bg-light); + border-radius: var(--border-radius); + min-height: 200px; +} + +.component-loading .loading-spinner { + width: 30px; + height: 30px; + border-width: 3px; + margin-bottom: var(--spacing-sm); +} + +.component-loading .loading-text { + font-size: var(--font-sm); +} + +/* ======================================== + 반응형 디자인 + ======================================== */ +@media (max-width: 768px) { + .navbar { + padding: var(--spacing-sm) 0; + } + + .nav-menu { + position: fixed; + left: -100%; + top: var(--navbar-height); + flex-direction: column; + background-color: var(--bg-white); + width: 100%; + text-align: center; + transition: var(--transition); + box-shadow: 0 10px 27px rgba(0, 0, 0, 0.05); + padding: var(--spacing-xl) 0; + z-index: 999; + } + + .nav-menu.active { + left: 0; + } + + .hamburger { + display: flex; + } + + .grid-2, + .grid-3, + .grid-4 { + grid-template-columns: 1fr; + gap: var(--spacing-lg); + } + + .section { + padding: var(--spacing-2xl) 0; + } + + .section-header h1, + .section-header h2 { + font-size: var(--font-3xl); + } + + .section-header p { + font-size: var(--font-base); + margin-bottom: var(--spacing-lg); + } + + .btn { + padding: var(--spacing-md) var(--spacing-lg); + font-size: var(--font-sm); + } + + .btn-lg { + padding: var(--spacing-lg) var(--spacing-xl); + font-size: var(--font-base); + } + + .cta-buttons { + flex-direction: column; + align-items: center; + gap: var(--spacing-md); + } + + .cta-buttons .btn { + width: 100%; + max-width: 280px; + } +} + +@media (max-width: 480px) { + .container { + padding: 0 var(--spacing-md); + } + + .section { + padding: var(--spacing-xl) 0; + } + + .section-header h1, + .section-header h2 { + font-size: var(--font-2xl); + } + + .section-header p { + font-size: var(--font-sm); + } +} \ No newline at end of file diff --git a/css/contact.css b/css/contact.css new file mode 100644 index 0000000..f0815e4 --- /dev/null +++ b/css/contact.css @@ -0,0 +1,493 @@ +/* ======================================== + Contact 페이지 전용 스타일 + ======================================== */ + +/* 페이지 헤더 */ +.page-header { + background: var(--gradient-main); + color: var(--text-white); + padding: var(--spacing-3xl) 0; + text-align: center; +} + +.page-header h1 { + font-size: var(--font-5xl); + margin-bottom: var(--spacing-md); +} + +.page-header p { + font-size: var(--font-xl); + opacity: 0.95; +} + +/* 연락처 정보 그리드 */ +.contact-info-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: var(--spacing-xl); + margin-bottom: var(--spacing-3xl); +} + +.contact-card { + text-align: center; + padding: var(--spacing-2xl); + background: var(--bg-white); + border-radius: var(--border-radius); + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.08); + transition: var(--transition); +} + +.contact-card:hover { + transform: translateY(-8px); + box-shadow: 0 12px 30px rgba(0, 0, 0, 0.15); +} + +.contact-icon { + font-size: 3rem; + margin-bottom: var(--spacing-lg); +} + +.contact-card h3 { + font-size: var(--font-xl); + margin-bottom: var(--spacing-md); + color: var(--text-primary); +} + +.contact-card p { + color: var(--text-secondary); + margin-bottom: var(--spacing-md); + font-size: var(--font-base); +} + +.contact-link { + display: inline-block; + color: var(--primary-color); + font-weight: 600; + font-size: var(--font-xs); + text-decoration: none; + padding: var(--spacing-sm) var(--spacing-md); + border: 2px solid var(--primary-color); + border-radius: var(--border-radius); + transition: var(--transition); + max-width: 100%; + text-align: center; +} + +.contact-link:hover { + background: var(--primary-color); + color: var(--text-white); +} + +/* 문의 폼 래퍼 */ +.contact-form-wrapper { + max-width: 800px; + margin: 0 auto; + background: var(--bg-white); + padding: var(--spacing-3xl); + border-radius: var(--border-radius); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1); +} + +/* 폼 스타일 */ +.contact-form { + width: 100%; +} + +.form-row { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--spacing-lg); + margin-bottom: var(--spacing-lg); +} + +.form-group { + margin-bottom: var(--spacing-lg); +} + +.form-group label { + display: block; + margin-bottom: var(--spacing-sm); + font-weight: 600; + color: var(--text-primary); + font-size: var(--font-base); +} + +.form-group input, +.form-group select, +.form-group textarea { + width: 100%; + padding: var(--spacing-md); + border: 2px solid #e5e7eb; + border-radius: var(--border-radius-sm); + font-size: var(--font-base); + font-family: inherit; + transition: var(--transition); + background: var(--bg-white); +} + +.form-group input:focus, +.form-group select:focus, +.form-group textarea:focus { + outline: none; + border-color: var(--primary-color); + box-shadow: 0 0 0 3px rgba(255, 136, 0, 0.1); +} + +.form-group textarea { + resize: vertical; + min-height: 120px; + line-height: 1.6; +} + +.form-group select { + cursor: pointer; +} + +/* 체크박스 그룹 */ +.checkbox-group { + display: flex; + align-items: flex-start; + gap: var(--spacing-md); + margin-bottom: var(--spacing-xl); +} + +.checkbox-label { + display: flex; + align-items: flex-start; + gap: var(--spacing-sm); + cursor: pointer; + line-height: 1.5; + font-size: var(--font-sm); +} + +.checkbox-label input[type="checkbox"] { + display: none; +} + +.checkmark { + width: 20px; + height: 20px; + border: 2px solid #d1d5db; + border-radius: 4px; + position: relative; + flex-shrink: 0; + background: var(--bg-white); + transition: var(--transition); +} + +.checkbox-label input[type="checkbox"]:checked + .checkmark { + background: var(--primary-color); + border-color: var(--primary-color); +} + +.checkbox-label input[type="checkbox"]:checked + .checkmark::after { + content: '✓'; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + color: var(--text-white); + font-size: 12px; + font-weight: bold; +} + +.privacy-link { + color: var(--primary-color); + text-decoration: underline; + font-size: var(--font-xs); + margin-left: auto; +} + +.privacy-link:hover { + color: var(--secondary-color); +} + +/* 폼 제출 버튼 */ +.form-submit { + display: flex; + gap: var(--spacing-md); + justify-content: center; + margin-top: var(--spacing-2xl); +} + +/* 위치 정보 */ +.location-wrapper { + margin-top: var(--spacing-2xl); +} + +.location-info { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--spacing-3xl); + align-items: start; +} + +.location-details h3 { + color: var(--primary-color); + margin: var(--spacing-xl) 0 var(--spacing-sm); + font-size: var(--font-lg); +} + +.location-details h3:first-child { + margin-top: 0; +} + +.location-details ul { + list-style: none; + padding: 0; +} + +.location-details li { + margin-bottom: var(--spacing-sm); + padding-left: var(--spacing-md); + position: relative; + line-height: 1.5; +} + +.location-details li::before { + content: '•'; + color: var(--primary-color); + position: absolute; + left: 0; + font-weight: bold; +} + +/* 지도 컨테이너 */ +.location-map { + position: sticky; + top: var(--spacing-xl); +} + +.map-container { + width: 100%; + height: 300px; + border-radius: var(--border-radius); + overflow: hidden; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); + margin-bottom: var(--spacing-lg); +} + +.map-placeholder { + width: 100%; + height: 100%; + background: var(--bg-light); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + color: var(--text-primary); + text-align: center; + padding: var(--spacing-xl); + border: 2px dashed var(--primary-color); + border-radius: var(--border-radius); +} + +.map-icon { + font-size: 4rem; + margin-bottom: var(--spacing-lg); + color: var(--primary-color); +} + +.map-placeholder h4 { + font-size: var(--font-xl); + margin-bottom: var(--spacing-md); + color: var(--text-primary); +} + +.map-placeholder p { + line-height: 1.6; + color: var(--text-secondary); +} + +/* 구글 맵 임베드 스타일 */ +.map-container iframe { + border-radius: var(--border-radius); +} + +.map-buttons { + display: flex; + gap: var(--spacing-md); + justify-content: center; +} + +.map-buttons .btn { + flex: 1; + text-align: center; + font-size: var(--font-sm); +} + +/* 개인정보처리방침 모달 */ +.modal { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + z-index: 1000; +} + +.modal.active { + display: flex; + align-items: center; + justify-content: center; +} + +.modal-content { + background: var(--bg-white); + border-radius: var(--border-radius); + max-width: 600px; + max-height: 80vh; + width: 90%; + overflow-y: auto; +} + +.modal-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: var(--spacing-xl); + border-bottom: 1px solid #e5e7eb; +} + +.modal-header h3 { + margin: 0; + color: var(--text-primary); +} + +.modal-close { + font-size: var(--font-2xl); + cursor: pointer; + color: var(--text-secondary); + width: 30px; + height: 30px; + display: flex; + align-items: center; + justify-content: center; +} + +.modal-close:hover { + color: var(--primary-color); +} + +.modal-body { + padding: var(--spacing-xl); +} + +.modal-body h4 { + color: var(--primary-color); + margin: var(--spacing-lg) 0 var(--spacing-sm); +} + +.modal-body h4:first-child { + margin-top: 0; +} + +.modal-body ul { + margin-bottom: var(--spacing-md); + padding-left: var(--spacing-lg); +} + +.modal-body li { + margin-bottom: var(--spacing-xs); +} + +/* CTA 섹션 */ +.cta-buttons { + display: flex; + gap: var(--spacing-md); + justify-content: center; + flex-wrap: wrap; + margin-top: var(--spacing-xl); +} + +/* 반응형 디자인 */ +@media (max-width: 768px) { + .page-header h1 { + font-size: var(--font-3xl); + } + + .page-header p { + font-size: var(--font-base); + } + + .contact-info-grid { + grid-template-columns: 1fr; + gap: var(--spacing-lg); + } + + .contact-form-wrapper { + padding: var(--spacing-xl); + margin: 0 var(--spacing-md); + } + + .form-row { + grid-template-columns: 1fr; + gap: 0; + } + + .location-info { + grid-template-columns: 1fr; + gap: var(--spacing-2xl); + } + + .location-map { + position: static; + } + + .form-submit { + flex-direction: column; + } + + .form-submit .btn { + width: 100%; + } + + .modal-content { + width: 95%; + margin: var(--spacing-md); + } + + .modal-header, + .modal-body { + padding: var(--spacing-lg); + } +} + +@media (max-width: 480px) { + .contact-card { + padding: var(--spacing-lg); + } + + .contact-icon { + font-size: 2.5rem; + } + + .contact-card h3 { + font-size: var(--font-lg); + } + + .contact-link { + font-size: var(--font-base); + padding: var(--spacing-sm); + } + + .map-container { + height: 250px; + } + + .map-buttons { + flex-direction: column; + } + + .checkbox-group { + flex-direction: column; + gap: var(--spacing-sm); + } + + .privacy-link { + margin-left: 0; + margin-top: var(--spacing-xs); + } +} \ No newline at end of file diff --git a/css/gallery.css b/css/gallery.css new file mode 100644 index 0000000..23a1f6a --- /dev/null +++ b/css/gallery.css @@ -0,0 +1,325 @@ +/* ======================================== + Gallery 페이지 전용 스타일 + ======================================== */ + +/* 페이지 헤더 */ +.page-header { + background: var(--gradient-main); + color: var(--text-white); + padding: var(--spacing-3xl) 0; + text-align: center; +} + +.page-header h1 { + font-size: var(--font-5xl); + margin-bottom: var(--spacing-md); +} + +.page-header p { + font-size: var(--font-xl); + opacity: 0.95; +} + +/* 갤러리 그리드 */ +.gallery-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: var(--spacing-xl); + margin-top: var(--spacing-2xl); +} + +.gallery-item { + position: relative; + background: var(--bg-white); + border-radius: var(--border-radius); + overflow: hidden; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); + transition: var(--transition); +} + +.gallery-item:hover { + transform: translateY(-8px); + box-shadow: 0 12px 30px rgba(0, 0, 0, 0.15); +} + +.gallery-img { + width: 100%; + height: 250px; + object-fit: cover; + transition: var(--transition); +} + +.gallery-item:hover .gallery-img { + transform: scale(1.05); +} + +.gallery-caption { + position: absolute; + bottom: 0; + left: 0; + right: 0; + background: linear-gradient(transparent, rgba(0, 0, 0, 0.8)); + color: var(--text-white); + padding: var(--spacing-lg); + font-weight: 500; + font-size: var(--font-base); + text-align: center; + transform: translateY(100%); + transition: var(--transition); +} + +.gallery-item:hover .gallery-caption { + transform: translateY(0); +} + +/* 라이트박스 모달 */ +.lightbox { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + background: rgba(0, 0, 0, 0.9); + z-index: 1000; + cursor: pointer; + overflow: hidden; +} + +.lightbox.active { + display: flex; + align-items: center; + justify-content: center; + padding: 20px; + box-sizing: border-box; +} + +.lightbox-content { + max-width: 70vw; + max-height: 70vh; + position: relative; + margin: auto; + display: block; +} + +.lightbox-img { + width: 100%; + height: auto; + max-height: 70vh; + object-fit: contain; + display: block; + border-radius: 8px; +} + +.lightbox-caption { + position: absolute; + bottom: -50px; + left: 50%; + transform: translateX(-50%); + color: var(--text-white); + font-size: var(--font-lg); + font-weight: 500; + text-align: center; + white-space: nowrap; +} + +.lightbox-close { + position: absolute; + top: -60px; + right: 0; + background: rgba(255, 255, 255, 0.9); + color: #333; + font-size: var(--font-xl); + cursor: pointer; + width: 45px; + height: 45px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + transition: var(--transition); + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); + border: 3px solid #fff; +} + +.lightbox-close::before { + content: '✕'; + font-weight: bold; + font-size: 18px; +} + +.lightbox-close:hover { + background: var(--primary-color); + color: white; + transform: scale(1.1); + box-shadow: 0 6px 20px rgba(255, 136, 0, 0.4); +} + +.lightbox-nav { + position: absolute; + top: 50%; + transform: translateY(-50%); + color: var(--text-white); + font-size: var(--font-2xl); + background: rgba(0, 0, 0, 0.5); + width: 50px; + height: 50px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: var(--transition); +} + +.lightbox-nav:hover { + background: var(--primary-color); + color: var(--text-white); +} + +.lightbox-prev { + left: -80px; +} + +.lightbox-next { + right: -80px; +} + +/* 갤러리 카테고리 필터 */ +.gallery-filters { + display: flex; + justify-content: center; + gap: var(--spacing-md); + margin-bottom: var(--spacing-2xl); + flex-wrap: wrap; +} + +.filter-btn { + padding: var(--spacing-sm) var(--spacing-lg); + border: 2px solid var(--primary-color); + background: transparent; + color: var(--primary-color); + border-radius: var(--border-radius-full); + cursor: pointer; + transition: var(--transition); + font-weight: 500; + font-size: var(--font-sm); +} + +.filter-btn:hover, +.filter-btn.active { + background: var(--primary-color); + color: var(--text-white); +} + +/* 로딩 스피너 */ +.gallery-loading { + display: none; + text-align: center; + padding: var(--spacing-2xl); +} + +.loading-spinner { + width: 40px; + height: 40px; + border: 3px solid #f3f3f3; + border-top: 3px solid var(--primary-color); + border-radius: 50%; + animation: spin 1s linear infinite; + margin: 0 auto var(--spacing-md); +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +/* 반응형 디자인 */ +@media (max-width: 768px) { + .page-header h1 { + font-size: var(--font-3xl); + } + + .page-header p { + font-size: var(--font-base); + } + + .gallery-grid { + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: var(--spacing-lg); + } + + .gallery-img { + height: 200px; + } + + .lightbox-nav { + font-size: var(--font-xl); + width: 40px; + height: 40px; + } + + .lightbox-prev { + left: -60px; + } + + .lightbox-next { + right: -60px; + } + + .lightbox-caption { + font-size: var(--font-base); + } +} + +@media (max-width: 480px) { + .gallery-grid { + grid-template-columns: 1fr; + gap: var(--spacing-md); + } + + .gallery-img { + height: 180px; + } + + .lightbox-content { + max-width: 90vw; + max-height: 75vh; + } + + .lightbox-nav { + position: fixed; + bottom: 20px; + } + + .lightbox-prev { + left: 20px; + } + + .lightbox-next { + right: 20px; + } + + .lightbox-close { + top: 20px; + right: 20px; + position: fixed; + } + + .lightbox-caption { + position: fixed; + bottom: 80px; + left: 50%; + transform: translateX(-50%); + font-size: var(--font-sm); + } + + .gallery-filters { + gap: var(--spacing-sm); + } + + .filter-btn { + font-size: var(--font-xs); + padding: var(--spacing-xs) var(--spacing-md); + } +} \ No newline at end of file diff --git a/css/main.css b/css/main.css new file mode 100644 index 0000000..fe12986 --- /dev/null +++ b/css/main.css @@ -0,0 +1,658 @@ +/* ======================================== + 메인 페이지 전용 스타일 - 모션캡쳐/버튜버 테마 + ======================================== */ + +/* Hero 섹션 */ +.hero-section { + min-height: calc(100vh - var(--navbar-height)); + display: flex; + align-items: center; + position: relative; + background: var(--gradient-warm); + overflow: hidden; + padding: var(--spacing-3xl) 0; +} + +.hero-bg { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: + radial-gradient(circle at 20% 50%, rgba(255, 136, 0, 0.1) 0%, transparent 50%), + radial-gradient(circle at 80% 80%, rgba(255, 153, 51, 0.1) 0%, transparent 50%); + z-index: 0; +} + +.hero-content { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--spacing-3xl); + align-items: center; + position: relative; + z-index: 1; +} + +.hero-title { + font-size: 2.7rem; + font-weight: 800; + line-height: 1.2; + color: var(--text-primary); + margin-bottom: var(--spacing-xs); +} + +.hero-subtitle { + font-size: 2.2rem; + font-weight: 700; +} + +.gradient-text { + background: var(--gradient-main); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.hero-description { + margin: var(--spacing-lg) 0 var(--spacing-xl); + color: #555; + font-size: 1.15rem; + line-height: 1.6; +} + +.hero-buttons { + display: flex; + gap: var(--spacing-md); + flex-wrap: wrap; + margin-bottom: var(--spacing-2xl); +} + +.btn-outline { + background: transparent; + border: 2px solid var(--primary-color); + color: var(--primary-color); +} + +.btn-outline:hover { + background: var(--primary-color); + color: var(--text-white); + transform: translateY(-3px); +} + +/* Hero 스펙 표시 */ +.hero-specs { + display: flex; + gap: var(--spacing-xl); + margin-top: var(--spacing-2xl); + padding-top: var(--spacing-xl); + border-top: 1px solid rgba(0, 0, 0, 0.1); +} + +.spec-item { + display: flex; + align-items: center; + gap: var(--spacing-sm); +} + +.spec-icon { + font-size: 1.2rem; +} + +.spec-text { + font-size: 0.95rem; + color: var(--text-secondary); + font-weight: 500; +} + +/* Hero 이미지 */ +.hero-image { + display: flex; + justify-content: center; + align-items: center; +} + +.logo-wrapper { + position: relative; +} + +.hero-logo { + max-width: 390px; + width: 100%; + height: auto; + filter: drop-shadow(0 10px 30px rgba(0, 0, 0, 0.1)); + animation: float 6s ease-in-out infinite; +} + +.logo-glow { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 120%; + height: 120%; + background: radial-gradient(circle, rgba(255, 136, 0, 0.2) 0%, transparent 70%); + filter: blur(40px); + animation: pulse 3s ease-in-out infinite; +} + +@keyframes float { + 0%, 100% { transform: translateY(0px); } + 50% { transform: translateY(-20px); } +} + +@keyframes pulse { + 0%, 100% { opacity: 0.5; } + 50% { opacity: 0.8; } +} + +/* Features 섹션 */ +.features-section { + padding: var(--spacing-3xl) 0; + background: linear-gradient(135deg, #ffffff 0%, #f8fafc 50%, #fff7ed 100%); +} + +.features-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: var(--spacing-xl); + margin-top: var(--spacing-2xl); + max-width: 1200px; + margin-left: auto; + margin-right: auto; +} + +.feature-card { + text-align: center; + padding: var(--spacing-2xl); + background: rgba(255, 255, 255, 0.8); + backdrop-filter: blur(10px); + border-radius: var(--border-radius); + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); + border: 1px solid rgba(255, 255, 255, 0.2); + transition: var(--transition); + position: relative; + overflow: hidden; + min-height: 200px; + display: flex; + flex-direction: column; + justify-content: center; +} + +.feature-card::before { + content: ''; + position: absolute; + top: -50%; + left: -50%; + width: 200%; + height: 200%; + background: radial-gradient(circle, var(--primary-color) 0%, transparent 70%); + opacity: 0; + transition: opacity 0.3s; +} + +.feature-card:hover::before { + opacity: 0.05; +} + +.feature-card:hover { + transform: translateY(-10px); + box-shadow: 0 15px 40px rgba(0, 0, 0, 0.12); +} + +.feature-icon-wrapper { + width: 80px; + height: 80px; + margin: 0 auto var(--spacing-lg); + background: var(--gradient-warm); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; +} + +.feature-icon { + font-size: 2.5rem; +} + +.feature-card h3 { + font-size: var(--font-xl); + margin-bottom: var(--spacing-md); + color: var(--text-primary); +} + +.feature-card p { + color: var(--text-secondary); + line-height: 1.6; +} + +/* Services Preview */ +.services-preview { + padding: var(--spacing-3xl) 0; +} + +.bg-gradient { + background: linear-gradient(135deg, #f8fafc 0%, #fff7ed 100%); +} + +.services-carousel { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: var(--spacing-xl); + margin-top: var(--spacing-2xl); + max-width: 1000px; + margin-left: auto; + margin-right: auto; +} + +.service-item { + background: rgba(255, 255, 255, 0.9); + backdrop-filter: blur(10px); + padding: var(--spacing-xl); + border-radius: var(--border-radius); + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.08); + border: 1px solid rgba(255, 255, 255, 0.3); + transition: var(--transition); + text-align: center; + cursor: pointer; + min-height: 160px; + display: flex; + flex-direction: column; + justify-content: center; +} + +.service-item.active { + background: linear-gradient(135deg, var(--primary-color), var(--primary-hover)); + color: var(--text-white); + transform: scale(1.05); +} + +.service-item:hover:not(.active) { + transform: translateY(-5px); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.12); +} + +.service-icon { + font-size: 2.5rem; + margin-bottom: var(--spacing-md); +} + +.service-item h3 { + font-size: var(--font-lg); + margin-bottom: var(--spacing-sm); +} + +.service-item.active h3, +.service-item.active p { + color: var(--text-white); +} + +/* Studio Preview */ +.studio-preview { + padding: var(--spacing-3xl) 0; + background: linear-gradient(135deg, #fff7ed 0%, #ffffff 50%, #f8fafc 100%); +} + +.preview-grid { + display: grid; + grid-template-columns: 2fr 1fr; + gap: var(--spacing-lg); + margin-top: var(--spacing-2xl); +} + +.preview-main, +.preview-item { + position: relative; + overflow: hidden; + border-radius: var(--border-radius); + cursor: pointer; +} + +.preview-img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.5s; +} + +.preview-main { + height: 400px; +} + +.preview-side { + display: flex; + flex-direction: column; + gap: var(--spacing-lg); +} + +.preview-item { + height: calc((400px - var(--spacing-lg)) / 2); +} + +.preview-overlay { + position: absolute; + bottom: 0; + left: 0; + right: 0; + background: linear-gradient(to top, rgba(0, 0, 0, 0.8), transparent); + color: var(--text-white); + padding: var(--spacing-xl); + transform: translateY(100%); + transition: transform 0.3s; +} + +.preview-main:hover .preview-overlay, +.preview-item:hover .preview-overlay { + transform: translateY(0); +} + +.preview-main:hover .preview-img, +.preview-item:hover .preview-img { + transform: scale(1.1); +} + +.preview-overlay h3 { + margin-bottom: var(--spacing-sm); +} + +/* Portfolio Preview */ +.portfolio-preview { + padding: var(--spacing-3xl) 0; +} + +.portfolio-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); + gap: var(--spacing-xl); + margin-top: var(--spacing-2xl); +} + +.portfolio-item { + text-align: center; +} + +.portfolio-video { + position: relative; + padding-bottom: 56.25%; /* 16:9 비율 */ + height: 0; + overflow: hidden; + border-radius: var(--border-radius); + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); +} + +.portfolio-video iframe { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border: none; +} + +.portfolio-item h3 { + margin-top: var(--spacing-md); + font-size: var(--font-xl); + color: var(--text-primary); +} + +/* 고객 후기 섹션 */ +.testimonials-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); + gap: var(--spacing-xl); + margin-top: var(--spacing-2xl); +} + +.testimonial-card { + background: var(--bg-white); + padding: var(--spacing-2xl); + border-radius: var(--border-radius); + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); + transition: var(--transition); + position: relative; + overflow: hidden; +} + +.testimonial-card::before { + content: '"'; + position: absolute; + top: var(--spacing-md); + left: var(--spacing-md); + font-size: 4rem; + color: rgba(255, 136, 0, 0.1); + font-family: Georgia, serif; + line-height: 1; +} + +.testimonial-card:hover { + transform: translateY(-5px); + box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12); +} + +.testimonial-content { + position: relative; + z-index: 1; +} + +.testimonial-stars { + font-size: 1.2rem; + margin-bottom: var(--spacing-md); +} + +.testimonial-card p { + font-size: var(--font-base); + line-height: 1.7; + color: var(--text-secondary); + margin-bottom: var(--spacing-lg); + font-style: italic; +} + +.testimonial-author { + display: flex; + align-items: center; + gap: var(--spacing-md); + padding-top: var(--spacing-lg); + border-top: 1px solid rgba(0, 0, 0, 0.1); +} + +.author-info strong { + display: block; + color: var(--text-primary); + font-size: var(--font-base); + margin-bottom: var(--spacing-xs); +} + +.author-info span { + color: var(--text-secondary); + font-size: var(--font-sm); +} + +/* CTA 섹션 */ +.cta-section { + padding: var(--spacing-3xl) 0; + position: relative; + overflow: hidden; +} + +.cta-bg { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: var(--gradient-warm); + z-index: 0; +} + +.cta-section .container { + position: relative; + z-index: 1; +} + +.cta-title { + font-size: var(--font-4xl); + color: var(--text-primary); + margin-bottom: var(--spacing-md); +} + +.cta-description { + font-size: var(--font-xl); + color: var(--text-secondary); + margin-bottom: var(--spacing-2xl); +} + +.cta-buttons { + display: flex; + gap: var(--spacing-md); + justify-content: center; + flex-wrap: wrap; + margin-bottom: var(--spacing-2xl); +} + +.btn-lg { + padding: var(--spacing-lg) var(--spacing-2xl); + font-size: var(--font-lg); +} + +.cta-section .btn-outline { + border-color: var(--primary-color); + color: var(--primary-color); +} + +.cta-section .btn-outline:hover { + background: var(--primary-color); + color: var(--text-white); +} + +.contact-info-quick { + display: flex; + gap: var(--spacing-2xl); + justify-content: center; + flex-wrap: wrap; + color: var(--text-secondary); + font-size: var(--font-sm); +} + +/* 유틸리티 클래스 */ +.text-center { + text-align: center; +} + +.mt-4 { + margin-top: var(--spacing-xl); +} + +.bg-light { + background-color: var(--bg-light); +} + +/* 반응형 디자인 */ +@media (max-width: 1024px) { + .hero-content { + grid-template-columns: 1fr; + text-align: center; + } + + .hero-image { + order: -1; + margin-bottom: var(--spacing-2xl); + } + + .hero-specs { + justify-content: center; + } + + .preview-grid { + grid-template-columns: 1fr; + } + + .preview-main { + height: 300px; + } + + .preview-side { + flex-direction: row; + } + + .preview-item { + height: 200px; + flex: 1; + } +} + +@media (max-width: 768px) { + .hero-title { + font-size: 2rem; + } + + .hero-subtitle { + font-size: 1.8rem; + } + + .hero-description { + font-size: 1rem; + } + + .hero-buttons { + justify-content: center; + } + + .hero-specs { + flex-direction: column; + align-items: center; + gap: var(--spacing-md); + } + + .services-carousel { + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: var(--spacing-lg); + } + + .service-item { + min-height: 140px; + } + + .portfolio-grid { + grid-template-columns: 1fr; + } + + .cta-title { + font-size: var(--font-3xl); + } + + .cta-description { + font-size: var(--font-base); + } +} + +@media (max-width: 480px) { + .hero-title { + font-size: 1.8rem; + } + + .hero-subtitle { + font-size: 1.5rem; + } + + .hero-logo { + max-width: 300px; + } + + .features-grid { + grid-template-columns: 1fr; + gap: var(--spacing-lg); + } + + .feature-card { + min-height: 180px; + } + + .preview-side { + flex-direction: column; + } + + .contact-info-quick { + flex-direction: column; + gap: var(--spacing-sm); + } +} \ No newline at end of file diff --git a/css/portfolio.css b/css/portfolio.css new file mode 100644 index 0000000..bdbcc29 --- /dev/null +++ b/css/portfolio.css @@ -0,0 +1,450 @@ +/* ======================================== + Portfolio 페이지 전용 스타일 + ======================================== */ + +/* 페이지 헤더 */ +.page-header { + background: var(--gradient-main); + color: var(--text-white); + padding: var(--spacing-3xl) 0; + text-align: center; +} + +.page-header h1 { + font-size: var(--font-5xl); + margin-bottom: var(--spacing-md); +} + +.page-header p { + font-size: var(--font-xl); + opacity: 0.95; +} + +/* YouTube 채널 카드 */ +.youtube-channel-card { + display: flex; + align-items: center; + justify-content: space-between; + padding: var(--spacing-2xl); + background: linear-gradient(135deg, #ff0000 0%, #cc0000 100%); + border-radius: var(--border-radius); + color: var(--text-white); + margin-bottom: var(--spacing-3xl); + box-shadow: 0 8px 25px rgba(255, 0, 0, 0.15); +} + +.channel-info { + display: flex; + align-items: center; + gap: var(--spacing-lg); +} + +.channel-icon { + font-size: 4rem; + opacity: 0.9; +} + +.channel-details h2 { + font-size: var(--font-2xl); + margin-bottom: var(--spacing-sm); +} + +.channel-details p { + font-size: var(--font-base); + opacity: 0.9; +} + +.youtube-channel-card .btn { + background: var(--text-white); + color: #ff0000; + font-weight: 700; + border: 2px solid var(--text-white); +} + +.youtube-channel-card .btn:hover { + background: transparent; + color: var(--text-white); + border-color: var(--text-white); +} + +/* 비디오 그리드 */ +.video-grid { + display: grid; + gap: var(--spacing-2xl); + margin-top: var(--spacing-2xl); +} + +.longform-grid { + grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); +} + +.shorts-grid { + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); +} + +.broadcast-grid { + grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); +} + +/* 비디오 카드 */ +.video-card { + background: var(--bg-white); + border-radius: var(--border-radius); + overflow: hidden; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.08); + transition: var(--transition); +} + +.video-card:hover { + transform: translateY(-8px); + box-shadow: 0 12px 30px rgba(0, 0, 0, 0.15); +} + +.video-card.featured { + border: 3px solid var(--primary-color); +} + +/* 비디오 래퍼 */ +.video-wrapper { + position: relative; + width: 100%; + height: 0; + padding-bottom: 56.25%; /* 16:9 비율 */ + overflow: hidden; +} + +.shorts-wrapper { + padding-bottom: 177.78%; /* 9:16 비율 */ +} + +.video-wrapper iframe { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border: none; +} + +/* 비디오 정보 */ +.video-info { + padding: var(--spacing-xl); +} + +.video-info h3 { + font-size: var(--font-xl); + margin-bottom: var(--spacing-md); + color: var(--text-primary); + line-height: 1.4; +} + +.video-info h4 { + font-size: var(--font-lg); + margin-bottom: var(--spacing-sm); + color: var(--text-primary); +} + +.video-info p { + color: var(--text-secondary); + line-height: 1.6; + margin-bottom: var(--spacing-md); +} + +.video-desc { + font-style: italic; + font-size: var(--font-sm); + color: var(--text-secondary); + margin-bottom: var(--spacing-md); +} + +/* 비디오 태그 */ +.video-tags { + display: flex; + gap: var(--spacing-sm); + flex-wrap: wrap; + margin-top: var(--spacing-md); +} + +.tag { + display: inline-block; + padding: var(--spacing-xs) var(--spacing-md); + background: rgba(255, 136, 0, 0.1); + color: var(--primary-color); + border-radius: var(--border-radius-full); + font-size: var(--font-xs); + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +/* 방송 정보 */ +.broadcast-info { + display: flex; + gap: var(--spacing-sm); + margin-top: var(--spacing-md); +} + +.platform { + display: inline-block; + padding: var(--spacing-xs) var(--spacing-sm); + background: var(--secondary-color); + color: var(--text-white); + border-radius: var(--border-radius-sm); + font-size: var(--font-xs); + font-weight: 600; +} + +.streamer { + display: inline-block; + padding: var(--spacing-xs) var(--spacing-sm); + background: var(--bg-light); + color: var(--text-primary); + border-radius: var(--border-radius-sm); + font-size: var(--font-xs); + font-weight: 500; +} + +/* 방송 알림 */ +.broadcast-notice { + display: flex; + align-items: center; + gap: var(--spacing-lg); + padding: var(--spacing-2xl); + background: linear-gradient(135deg, rgba(255, 0, 0, 0.1), rgba(255, 136, 0, 0.1)); + border-radius: var(--border-radius); + border: 2px solid rgba(255, 0, 0, 0.2); + margin-bottom: var(--spacing-2xl); +} + +.notice-icon { + font-size: 3rem; + flex-shrink: 0; +} + +.notice-content h3 { + color: var(--text-primary); + margin-bottom: var(--spacing-sm); + font-size: var(--font-xl); +} + +.notice-content p { + color: var(--text-secondary); + line-height: 1.6; +} + +/* 기술 특징 */ +.tech-features { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: var(--spacing-2xl); + margin-top: var(--spacing-2xl); +} + +.tech-feature { + text-align: center; + padding: var(--spacing-2xl); + background: var(--bg-white); + border-radius: var(--border-radius); + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.08); + transition: var(--transition); +} + +.tech-feature:hover { + transform: translateY(-5px); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.12); +} + +.tech-icon { + font-size: 3rem; + margin-bottom: var(--spacing-lg); +} + +.tech-feature h3 { + font-size: var(--font-xl); + margin-bottom: var(--spacing-md); + color: var(--text-primary); +} + +.tech-feature p { + color: var(--text-secondary); + line-height: 1.6; +} + +/* CTA 섹션 */ +.cta-section { + background: var(--gradient-warm); + padding: var(--spacing-3xl) 0; +} + +.cta-section h2 { + font-size: var(--font-4xl); + margin-bottom: var(--spacing-md); + color: var(--text-primary); +} + +.cta-section p { + font-size: var(--font-xl); + margin-bottom: var(--spacing-2xl); + color: var(--text-secondary); +} + +.cta-buttons { + display: flex; + gap: var(--spacing-md); + justify-content: center; + flex-wrap: wrap; +} + +.cta-section .btn-outline { + border-color: var(--primary-color); + color: var(--primary-color); +} + +.cta-section .btn-outline:hover { + background: var(--primary-color); + color: var(--text-white); +} + +/* 로딩 상태 */ +.video-loading { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + color: var(--text-secondary); + font-size: var(--font-lg); + z-index: 1; +} + +.video-wrapper::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: var(--bg-light); + z-index: 0; + transition: opacity 0.3s ease; +} + +.video-wrapper.loaded::before { + opacity: 0; + pointer-events: none; +} + +/* 비디오 카운터 */ +.video-counter { + position: absolute; + top: var(--spacing-md); + right: var(--spacing-md); + background: rgba(0, 0, 0, 0.8); + color: var(--text-white); + padding: var(--spacing-xs) var(--spacing-sm); + border-radius: var(--border-radius-sm); + font-size: var(--font-xs); + font-weight: 600; +} + +/* 반응형 디자인 */ +@media (max-width: 768px) { + .page-header h1 { + font-size: var(--font-3xl); + } + + .page-header p { + font-size: var(--font-base); + } + + .youtube-channel-card { + flex-direction: column; + text-align: center; + gap: var(--spacing-lg); + } + + .channel-info { + flex-direction: column; + text-align: center; + } + + .channel-icon { + font-size: 3rem; + } + + .shorts-grid { + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + } + + .broadcast-grid { + grid-template-columns: 1fr; + } + + .broadcast-notice { + flex-direction: column; + text-align: center; + } + + .tech-features { + grid-template-columns: 1fr; + } + + .video-info { + padding: var(--spacing-lg); + } + + .video-info h3 { + font-size: var(--font-lg); + } + + .cta-buttons { + flex-direction: column; + align-items: center; + } + + .cta-buttons .btn { + width: 100%; + max-width: 300px; + } +} + +@media (max-width: 480px) { + .youtube-channel-card { + padding: var(--spacing-lg); + margin: 0 var(--spacing-md) var(--spacing-2xl); + } + + .channel-details h2 { + font-size: var(--font-xl); + } + + .shorts-grid { + grid-template-columns: 1fr; + } + + .video-card { + margin: 0 var(--spacing-sm); + } + + .video-tags { + gap: var(--spacing-xs); + } + + .tag { + font-size: var(--font-xxs); + padding: var(--spacing-xxs) var(--spacing-sm); + } + + .broadcast-info { + flex-direction: column; + gap: var(--spacing-xs); + align-items: flex-start; + } + + .tech-feature { + padding: var(--spacing-xl); + } + + .tech-icon { + font-size: 2.5rem; + } +} \ No newline at end of file diff --git a/css/qna.css b/css/qna.css new file mode 100644 index 0000000..5e69f0e --- /dev/null +++ b/css/qna.css @@ -0,0 +1,458 @@ +/* ======================================== + FAQ 페이지 전용 스타일 + ======================================== */ + +/* 페이지 헤더 */ +.page-header { + background: var(--gradient-main); + color: var(--text-white); + padding: var(--spacing-3xl) 0; + text-align: center; +} + +.page-header h1 { + font-size: var(--font-5xl); + margin-bottom: var(--spacing-md); +} + +.page-header p { + font-size: var(--font-xl); + opacity: 0.95; +} + +/* FAQ 검색 */ +.faq-search { + max-width: 600px; + margin: 0 auto; + position: relative; +} + +.search-box { + position: relative; + width: 100%; +} + +.search-box input { + width: 100%; + padding: var(--spacing-lg) var(--spacing-xl); + padding-right: 60px; + border: 2px solid #e5e7eb; + border-radius: var(--border-radius-full); + font-size: var(--font-lg); + background: var(--bg-white); + transition: var(--transition); +} + +.search-box input:focus { + outline: none; + border-color: var(--primary-color); + box-shadow: 0 0 0 4px rgba(255, 136, 0, 0.1); +} + +.search-btn { + position: absolute; + right: var(--spacing-md); + top: 50%; + transform: translateY(-50%); + background: none; + border: none; + font-size: var(--font-xl); + cursor: pointer; + padding: var(--spacing-sm); + border-radius: 50%; + transition: var(--transition); +} + +.search-btn:hover { + background: rgba(255, 136, 0, 0.1); +} + +/* 검색 제안 */ +.search-suggestions { + position: absolute; + top: 100%; + left: 0; + right: 0; + background: var(--bg-white); + border: 1px solid #e5e7eb; + border-radius: var(--border-radius); + margin-top: var(--spacing-sm); + max-height: 200px; + overflow-y: auto; + z-index: 100; + display: none; +} + +.search-suggestions.active { + display: block; +} + +.suggestion-item { + padding: var(--spacing-md) var(--spacing-lg); + cursor: pointer; + transition: var(--transition); + border-bottom: 1px solid #f3f4f6; +} + +.suggestion-item:last-child { + border-bottom: none; +} + +.suggestion-item:hover { + background: rgba(255, 136, 0, 0.05); +} + +/* FAQ 카테고리 섹션 */ +.faq-category-section { + padding: var(--spacing-md) 0 var(--spacing-sm); + background: var(--bg-light); +} + +/* FAQ 카테고리 */ +.faq-categories { + display: flex; + justify-content: center; + gap: var(--spacing-sm); + flex-wrap: wrap; +} + +.category-btn { + padding: var(--spacing-sm) var(--spacing-lg); + border: 2px solid #e5e7eb; + background: var(--bg-white); + color: var(--text-secondary); + border-radius: var(--border-radius-full); + cursor: pointer; + transition: var(--transition); + font-size: var(--font-sm); + font-weight: 500; +} + +.category-btn:hover, +.category-btn.active { + border-color: var(--primary-color); + background: var(--primary-color); + color: var(--text-white); +} + +/* FAQ 리스트 */ +.faq-list { + max-width: 800px; + margin: 0 auto; +} + +.faq-item { + background: var(--bg-white); + border: 1px solid #e5e7eb; + border-radius: var(--border-radius); + margin-bottom: var(--spacing-lg); + overflow: hidden; + transition: var(--transition); +} + +.faq-item:hover { + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); +} + +.faq-item.hidden { + display: none; +} + +.faq-question { + display: flex; + justify-content: space-between; + align-items: center; + padding: var(--spacing-xl); + cursor: pointer; + background: var(--bg-white); + transition: var(--transition); +} + +.faq-question:hover { + background: rgba(255, 136, 0, 0.02); +} + +.faq-question h3 { + margin: 0; + font-size: var(--font-lg); + color: var(--text-primary); + flex: 1; + padding-right: var(--spacing-md); +} + +.faq-toggle { + font-size: var(--font-2xl); + color: var(--primary-color); + font-weight: bold; + width: 30px; + height: 30px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 50%; + background: rgba(255, 136, 0, 0.1); + transition: var(--transition); + flex-shrink: 0; +} + +.faq-item.active .faq-toggle { + transform: rotate(45deg); + background: var(--primary-color); + color: var(--text-white); +} + +.faq-answer { + padding: 0 var(--spacing-xl); + max-height: 0; + overflow: hidden; + transition: max-height 0.3s ease, padding 0.3s ease; + background: var(--bg-light); +} + +.faq-item.active .faq-answer { + padding: var(--spacing-xl); + max-height: 5000px; + overflow: visible; +} + +.faq-answer p { + margin-bottom: var(--spacing-md); + line-height: 1.7; + color: var(--text-secondary); +} + +.faq-answer ul { + margin: var(--spacing-md) 0; + padding-left: var(--spacing-lg); +} + +.faq-answer li { + margin-bottom: var(--spacing-sm); + line-height: 1.6; + color: var(--text-secondary); +} + +.faq-answer strong { + color: var(--primary-color); + font-weight: 600; +} + +/* 정책 테이블 */ +.policy-table { + margin: var(--spacing-lg) 0; + border-radius: var(--border-radius-sm); + overflow: hidden; + border: 1px solid #e5e7eb; +} + +.policy-row { + display: flex; + justify-content: space-between; + padding: var(--spacing-md); + border-bottom: 1px solid #e5e7eb; + background: var(--bg-white); +} + +.policy-row:last-child { + border-bottom: none; +} + +.policy-time { + font-weight: 600; + color: var(--text-primary); + min-width: 80px; +} + +.policy-desc { + color: var(--text-secondary); +} + +/* 가격 테이블 */ +.pricing-table { + margin: var(--spacing-lg) 0; +} + +.pricing-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: var(--spacing-md); + border-bottom: 1px solid #e5e7eb; + background: var(--bg-white); +} + +.pricing-item:last-child { + border-bottom: none; +} + +.service-name { + font-weight: 500; + color: var(--text-primary); +} + +.service-price { + font-weight: 700; + color: var(--primary-color); + font-size: var(--font-lg); +} + +/* CTA 섹션 */ +.cta-buttons { + display: flex; + gap: var(--spacing-md); + justify-content: center; + flex-wrap: wrap; + margin-top: var(--spacing-xl); +} + +/* 검색 결과 하이라이트 */ +.search-highlight { + background: rgba(255, 136, 0, 0.3); + padding: 2px 4px; + border-radius: 3px; + font-weight: 500; +} + +/* 로딩 스타일 */ +.faq-loading { + text-align: center; + padding: var(--spacing-2xl); + display: none; +} + +.faq-loading.active { + display: block; +} + +.loading-spinner { + width: 30px; + height: 30px; + border: 2px solid #f3f3f3; + border-top: 2px solid var(--primary-color); + border-radius: 50%; + animation: spin 1s linear infinite; + margin: 0 auto var(--spacing-md); +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +/* 검색 결과 없음 */ +.no-results { + text-align: center; + padding: var(--spacing-3xl); + color: var(--text-secondary); + display: none; +} + +.no-results.active { + display: block; +} + +.no-results-icon { + font-size: 4rem; + margin-bottom: var(--spacing-lg); +} + +/* 반응형 디자인 */ +@media (max-width: 768px) { + .page-header h1 { + font-size: var(--font-3xl); + } + + .page-header p { + font-size: var(--font-base); + } + + .search-box input { + font-size: var(--font-base); + padding: var(--spacing-lg); + padding-right: 50px; + } + + .search-btn { + font-size: var(--font-lg); + } + + .faq-categories { + gap: var(--spacing-xs); + } + + .category-btn { + font-size: var(--font-xs); + padding: var(--spacing-xs) var(--spacing-md); + } + + .faq-question { + padding: var(--spacing-lg); + } + + .faq-question h3 { + font-size: var(--font-base); + } + + .faq-toggle { + font-size: var(--font-xl); + width: 25px; + height: 25px; + } + + .faq-item.active .faq-answer { + padding: var(--spacing-lg); + } + + .policy-row { + flex-direction: column; + gap: var(--spacing-xs); + } + + .policy-time { + min-width: auto; + font-size: var(--font-sm); + } + + .pricing-item { + flex-direction: column; + align-items: flex-start; + gap: var(--spacing-xs); + } + + .cta-buttons { + flex-direction: column; + align-items: center; + } + + .cta-buttons .btn { + width: 100%; + max-width: 300px; + } +} + +@media (max-width: 480px) { + .faq-search { + margin: 0 var(--spacing-md); + } + + .faq-list { + margin: 0 var(--spacing-md); + } + + .faq-question { + padding: var(--spacing-md); + } + + .faq-item.active .faq-answer { + padding: var(--spacing-md); + } + + .faq-answer p, + .faq-answer li { + font-size: var(--font-sm); + } + + .service-price { + font-size: var(--font-base); + } +} \ No newline at end of file diff --git a/css/services.css b/css/services.css new file mode 100644 index 0000000..d6d6fd8 --- /dev/null +++ b/css/services.css @@ -0,0 +1,479 @@ +/* ======================================== + Services 페이지 전용 스타일 + ======================================== */ + +/* 페이지 헤더 */ +.page-header { + background: var(--gradient-main); + color: var(--text-white); + padding: var(--spacing-3xl) 0; + text-align: center; +} + +.page-header h1 { + font-size: var(--font-5xl); + margin-bottom: var(--spacing-md); +} + +.page-header p { + font-size: var(--font-xl); + opacity: 0.95; +} + +/* 서비스 테이블 */ +.services-table-wrapper { + margin-bottom: var(--spacing-2xl); +} + +.services-table-wrapper .card { + overflow: hidden; +} + +.services-table-wrapper h3 { + margin-bottom: var(--spacing-lg); + font-size: var(--font-2xl); + color: var(--text-primary); +} + +.table-responsive { + overflow-x: auto; + border-radius: var(--border-radius-sm); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +.services-table { + width: 100%; + border-collapse: collapse; + background: var(--bg-white); +} + +.services-table th, +.services-table td { + padding: var(--spacing-lg); + text-align: left; + border-bottom: 1px solid #e5e7eb; +} + +.services-table th { + background: var(--bg-light); + font-weight: 700; + color: var(--text-primary); + text-align: center; +} + +.services-table tbody tr:hover { + background: rgba(255, 136, 0, 0.02); +} + +.main-service { + background: linear-gradient(135deg, rgba(255, 136, 0, 0.05), rgba(255, 153, 51, 0.05)); +} + +.service-name { + display: flex; + align-items: center; + gap: var(--spacing-sm); +} + +.service-icon { + font-size: 1.5rem; +} + +.service-features { + list-style: none; + padding: 0; +} + +.service-features li { + margin-bottom: var(--spacing-sm); + padding-left: var(--spacing-lg); + position: relative; +} + +.service-features li::before { + content: '•'; + color: var(--primary-color); + position: absolute; + left: 0; + font-weight: bold; +} + +.pricing { + text-align: center; + min-width: 180px; +} + +.price-main { + font-size: var(--font-xl); + font-weight: 700; + color: var(--primary-color); + margin-bottom: var(--spacing-xs); +} + +.price-sub { + font-size: var(--font-sm); + color: var(--text-secondary); + margin-bottom: var(--spacing-sm); +} + +.price-detail { + font-size: var(--font-sm); + line-height: 1.5; +} + +/* 대관 절차 */ +.process-flow { + display: flex; + align-items: center; + justify-content: center; + flex-wrap: wrap; + gap: var(--spacing-lg); + margin: var(--spacing-xl) 0; + padding: var(--spacing-xl); + background: var(--bg-light); + border-radius: var(--border-radius); +} + +.process-step { + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + flex: 1; + min-width: 150px; +} + +.step-number { + width: 50px; + height: 50px; + border-radius: 50%; + background: var(--gradient-main); + color: var(--text-white); + display: flex; + align-items: center; + justify-content: center; + font-size: var(--font-xl); + font-weight: 700; + margin-bottom: var(--spacing-md); +} + +.step-content h4 { + font-size: var(--font-lg); + margin-bottom: var(--spacing-sm); + color: var(--text-primary); +} + +.step-content p { + font-size: var(--font-sm); + color: var(--text-secondary); +} + +.process-arrow { + font-size: var(--font-2xl); + color: var(--primary-color); + font-weight: bold; +} + +/* 예약 버튼 */ +.booking-buttons { + display: flex; + gap: var(--spacing-md); + justify-content: center; + margin: var(--spacing-xl) 0 var(--spacing-sm); + flex-wrap: wrap; +} + +.booking-note { + text-align: center; + font-size: var(--font-sm); + color: var(--text-secondary); + margin-bottom: var(--spacing-xl); +} + +/* 이메일 양식 */ +.email-form { + margin-top: var(--spacing-2xl); + padding: var(--spacing-xl); + background: var(--bg-light); + border-radius: var(--border-radius); + border: 2px solid var(--primary-color); +} + +.email-form h4 { + color: var(--primary-color); + margin-bottom: var(--spacing-md); + font-size: var(--font-xl); +} + +.email-template { + background: var(--bg-white); + padding: var(--spacing-xl); + border-radius: var(--border-radius-sm); + margin: var(--spacing-lg) 0; + border: 1px solid #e5e7eb; +} + +.email-field { + margin-bottom: var(--spacing-md); + font-size: var(--font-base); + word-break: break-all; +} + +.form-section { + margin-bottom: var(--spacing-xl); +} + +.form-section h5 { + color: var(--text-primary); + margin-bottom: var(--spacing-sm); + font-size: var(--font-base); + font-weight: 600; +} + +.form-help { + font-size: var(--font-sm); + color: var(--text-secondary); + margin-bottom: var(--spacing-sm); + line-height: 1.4; +} + +.form-placeholder { + background: #f8f9fa; + padding: var(--spacing-md); + border-radius: var(--border-radius-sm); + border: 1px dashed #d1d5db; + font-family: monospace; + font-size: var(--font-sm); + color: var(--text-secondary); +} + +.email-send { + text-align: center; + margin-top: var(--spacing-xl); +} + +/* 정보 리스트 */ +.info-list { + list-style: none; + padding: 0; +} + +.info-list li { + margin-bottom: var(--spacing-md); + padding-left: var(--spacing-lg); + position: relative; + line-height: 1.6; +} + +.info-list li::before { + content: '✓'; + color: var(--primary-color); + position: absolute; + left: 0; + font-weight: bold; +} + +/* 환불 테이블 */ +.refund-table { + width: 100%; + border-collapse: collapse; + background: var(--bg-white); +} + +.refund-table th, +.refund-table td { + padding: var(--spacing-md); + text-align: center; + border-bottom: 1px solid #e5e7eb; +} + +.refund-table th { + background: var(--bg-light); + font-weight: 600; + color: var(--text-primary); +} + +.refund-100 { color: #10b981; font-weight: 600; } +.refund-70 { color: #f59e0b; font-weight: 600; } +.refund-50 { color: #f97316; font-weight: 600; } +.refund-0 { color: #ef4444; font-weight: 600; } + +/* 장비 그리드 */ +.equipment-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: var(--spacing-xl); + margin-top: var(--spacing-2xl); +} + +.equipment-card { + text-align: center; + padding: var(--spacing-2xl); + background: var(--bg-white); + border-radius: var(--border-radius); + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.08); + transition: var(--transition); +} + +.equipment-card:hover { + transform: translateY(-5px); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.12); +} + +.equipment-icon { + font-size: 3rem; + margin-bottom: var(--spacing-lg); +} + +.equipment-card h3 { + font-size: var(--font-xl); + margin-bottom: var(--spacing-md); + color: var(--text-primary); +} + +.equipment-card p { + color: var(--text-secondary); + line-height: 1.6; +} + +/* 그리드 레이아웃 */ +.grid { + display: grid; + gap: var(--spacing-xl); + margin: var(--spacing-xl) 0; +} + +.grid-2 { + grid-template-columns: 1fr 1fr; +} + +.grid-3 { + grid-template-columns: repeat(3, 1fr); +} + +.card { + background: var(--bg-white); + padding: var(--spacing-2xl); + border-radius: var(--border-radius); + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08); + margin-bottom: var(--spacing-xl); +} + +.card:last-child { + margin-bottom: 0; +} + +.card h3 { + color: var(--text-primary); + margin-bottom: var(--spacing-lg); + font-size: var(--font-xl); +} + +/* CTA 섹션 */ +.cta-section { + background: var(--gradient-warm); + padding: var(--spacing-3xl) 0; +} + +.cta-section h2 { + font-size: var(--font-4xl); + margin-bottom: var(--spacing-md); + color: var(--text-primary); +} + +.cta-section p { + font-size: var(--font-xl); + margin-bottom: var(--spacing-2xl); + color: var(--text-secondary); +} + +.cta-buttons { + display: flex; + gap: var(--spacing-md); + justify-content: center; + flex-wrap: wrap; +} + +.cta-section .btn-outline { + border-color: var(--primary-color); + color: var(--primary-color); +} + +.cta-section .btn-outline:hover { + background: var(--primary-color); + color: var(--text-white); +} + +/* 반응형 디자인 */ +@media (max-width: 768px) { + .page-header h1 { + font-size: var(--font-3xl); + } + + .page-header p { + font-size: var(--font-base); + } + + .services-table th, + .services-table td { + padding: var(--spacing-md); + font-size: var(--font-sm); + } + + .process-flow { + flex-direction: column; + } + + .process-arrow { + transform: rotate(90deg); + } + + .booking-buttons { + flex-direction: column; + align-items: center; + } + + .booking-buttons .btn { + width: 100%; + max-width: 300px; + } + + .equipment-grid { + grid-template-columns: 1fr; + } + + .grid-2, + .grid-3 { + grid-template-columns: 1fr; + gap: var(--spacing-lg); + } + + .card { + margin-bottom: var(--spacing-lg); + padding: var(--spacing-xl); + } +} + +@media (max-width: 480px) { + .services-table { + font-size: var(--font-xs); + } + + .pricing { + min-width: 120px; + } + + .price-main { + font-size: var(--font-base); + } + + .process-step { + min-width: 120px; + } + + .step-number { + width: 40px; + height: 40px; + font-size: var(--font-base); + } +} \ No newline at end of file diff --git a/gallery.html b/gallery.html new file mode 100644 index 0000000..8d5b456 --- /dev/null +++ b/gallery.html @@ -0,0 +1,76 @@ + + + + + + 스튜디오 갤러리 - 밍글 스튜디오 + + + + + + + +
+ + + + + + +
+
+ +
+
+ + + + + + \ No newline at end of file diff --git a/index.html b/index.html index de72222..01b8a5d 100644 --- a/index.html +++ b/index.html @@ -7,1289 +7,380 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + - - - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - -
-
-
-

밍글스튜디오
MINGLE STUDIO

-

기술과 창의력 열정이 한데 섞여 새로운 가치가 만들어지는 공간

- 회사 소개 보기 -
-
- 밍글 스튜디오 로고 -
-
-
- - -
-
-
-

About

-
-

회사명: 밍글 스튜디오 (mingle studio)  |  설립일: 2025년 7월 15일

-

슬로건: "모두가 어우러진 즐거운 창작공간"

-

의미: Mingle Studio는 기술자와 크리에이터 그리고 시청자가 함께 어우러지는 버추얼 콘텐츠 제작 공간입니다. 최첨단 광학식 모션캡처 기술로 버추얼 캐릭터의 살아 숨쉬는 감정과 움직임을 담아 새로운 세대의 디지털 퍼포먼스를 실현합니다.

-
-
-
-

회사 소개

-

밍글 스튜디오는 창작자와 기술, 사람과 사람 사이의 '어우러짐'을 통해 새로운 콘텐츠를 만들어가는 모션 캡쳐 기반의 창작 공간입니다.
설립 이후, 누구나 편하게 사용 가능한 스튜디오 대관 서비스를 중심으로 버추얼 콘텐츠 제작 환경을 제공합니다.

-
-
-

연혁 / 타임라인

- - - - - - -
날짜이벤트
2025년 7월 15일밍글 스튜디오 회사 설립
2025년 8월 1일밍글 스튜디오 오픈
-
-
-

Team

-

각 분야의 전문가들이 함께 협업하며 콘텐츠 제작을 지원합니다.

-
-
-
-

김희진 (JAYJAY)

-
대표 / 3D 아티스트
-
배경/리소스 제작, 인사 및 프로젝트 관리
-
-
-

김광진 (KINDNICK)

-
CTO / 테크니컬 디렉터
-
스튜디오 전체 기술 운영, 모션캡쳐 장비 관리, 음향 시스템, 엔진 프로그래밍 등
-
-
-

이승민 (YAMO)

-
CCO / 콘텐츠 디렉터
-
캡쳐 디렉팅, 배우 모션 클린업, 카메라 무빙, 퍼포먼스 연출 등
-
-
-
-
- -
-
-
-

주요 서비스 소개

-
- - -
-

서비스 항목 및 요금

- - - - - - - - - - - - - - - - - - - - - - - - - -
서비스 항목설명요금
모션캡쳐 스튜디오 대관 - • 28대의 광학식 카메라 시스템 (OptiTrack)
- • 모션캡쳐 수트 및 장갑 지원 (Rokoko Glove)
- • 스튜디오 면적: 8m(가로) x 7m(세로) x 2.6m(높이)
- • 실시간 모니터링 장비 보유
- • 전신 및 페이셜 모션캡쳐 가능
- • 동시 이용가능 인원: 최대 4인
- • 모션 녹화 파일 제공
- • 실시간 오퍼레이팅 지원 -
- 시간당 220,000원
- (VAT 포함)
- 최소 이용: 2시간

- 인원 요금:
- • 기본 인원: 2인
- • 추가 인원: +110,000원/시간당 -
모션 리타겟팅모션 데이터의 리타겟팅 지원별도 문의
(프로젝트별 견적)
실시간 스트리밍실시간 스트리밍 서비스준비중
-
- - -
-

서비스 이용 안내

- -

1) 스튜디오 대관 절차

-
-
- 이메일 문의 - - 담당자 확인 및 세부사항 협의 - - 전액 결제 - - 예약 확정 -
-
- - 📅 네이버 예약 바로가기 -

※ 네이버 플레이스를 통해 실시간 일정 확인 및 예약이 가능합니다

-
- - -
- -

2) 예약 안내

-
    -
  • 스튜디오 예약은 이용 희망일로부터 최소 2주 전에 신청하시는 것을 권장합니다.
  • -
  • 예약 확정 후 고객의 사정으로 인한 예약 취소 시 일정 기준에 따른 위약금이 발생합니다.
  • -
- -

3) 취소 환불 규정

- - - - - - - - - - - - - - - - - - - - - - - - - -
취소 시점환불 비율
예약일로부터 7일 전100% 환불
예약일로부터 3일 전70% 환불
예약일로부터 1일 전50% 환불
당일 취소환불 불가
- -

4) 방문 안내

-
    -
  • 본 촬영 전 모션캡쳐 수트 착용 등의 준비시간이 소요되므로 촬영예정 시간 최소 30분 전에 방문 부탁드립니다. (준비시간은 이용시간에 포함되지 않습니다.)
  • -
  • 안경, 귀걸이 등 반사가 잘 되는 재질의 악세사리는 촬영 시 가급적 착용을 자제하여 주시기 바랍니다.
  • -
-
- - -
-

스튜디오 이용 시 유의사항

-
    -
  • 스튜디오 내 모든 장비 및 설비는 소중히 다루어 주시기를 부탁드립니다.
  • -
  • 모션캡쳐 장비이용이 익숙하지 않으신 경우 사전에 운영진의 안내를 받으시거나 도움을 요청해 주세요. 정성껏 도와드리겠습니다.
  • -
  • 쾌적한 촬영환경과 장비 보호를 위해 촬영공간 내 음식물 반입 및 섭취를 지양해 주시기 바랍니다.
  • -
  • 대여 중 고객님의 고의 또는 과실로 인한 장비의 훼손 또는 분실이 발생한 경우, 수리 또는 교체에 필요한 비용이 청구될 수 있습니다.
  • -
-
-
-
- - -
-
-
-

Portfolio

-

밍글 스튜디오에서 제작하거나 협업한 영상 콘텐츠는 YouTube 링크를 통해 확인하실 수 있습니다.

-
- -
-
- - - - - + + + + + + - - + + + + + + +
- -
+ +
+
-
-

Contact

-

예약 문의 또는 협업 제안은 언제든지 이메일로 연락주세요.

-
-
- 이메일: minglestudio.mocap@gmail.com
- 연락처: 010-9288-9190
- 주소: (21330) 인천광역시 부평구 주부토로 236
- 인천테크노밸리 A동 B105호
-
- 오시는 길
- - 인천 7호선 갈산역 하차 → 도보 약 7분 거리
- - 건물 내 지하 주차 가능 (※ 2시간 무료) -
- -
-
-
- - -
-
-
-

FAQ – 자주 묻는 질문

-
-
    -
  • Q1. 스튜디오 대관은 어떻게 예약하나요?
    A. 이메일 문의를 통해 예약하실 수 있습니다.
    📧 minglestudio.mocap@gmail.com

    - 📅 네이버 예약 바로가기
    -

    ※ 네이버 플레이스를 통해 실시간 일정 확인 및 예약이 가능합니다

    - -
  • -
  • Q2. 최소 대관 시간은 어떻게 되나요?
    A. 최소 대관은 2시간부터 가능합니다.
  • -
  • Q3. 대관은 얼마나 전에 예약해야 하나요?
    A. 최소 2주 전에 연락주시면 원활하게 준비가 가능합니다.
  • -
  • Q4. 현장 결제가 가능한가요?
    A. 네, 가능합니다.
  • -
  • Q5. 세금계산서 발행이 가능한가요?
    A. 네, 사업자용 세금계산서 발행 가능합니다.
  • -
  • Q6. 예약금 제도와 환불 규정이 있나요?
    A. 아래는 환불 규정입니다:
    취소 시점환불 비율
    예약일로부터 7일 전100% 환불
    예약일로부터 3일 전70% 환불
    예약일로부터 1일 전50% 환불
    당일 취소환불 불가
  • -
  • Q7. 모션 캡쳐 데이터는 어떤 형식으로 제공되나요?
    A. FBX, ANIM 포맷으로 제공되며, 문의 시 세부사항 안내해드립니다.
  • -
  • Q8. 리타겟팅도 함께 제공되나요?
    A. 기본 리타겟팅이 포함되어 있으며, 추가적인 클린업/후처리는 별도 견적 협의 후 제공됩니다.
  • -
  • Q9. 실시간 미리보기나 스트리밍이 가능한가요?
    A. 실시간 미리보기는 가능하며, 실시간 스트리밍은 지원 예정입니다.
  • -
  • Q10. 장비 사용이 익숙하지 않아도 괜찮을까요?
    A. 스튜디오에는 담당 인력이 배치되어 있어 장비 세팅 및 사용을 지원해드립니다.
  • -
  • Q11. 얼굴 캡쳐나 음성 녹음도 가능한가요?
    A. 가능합니다. 다만 예약 시 미리 요청해주셔야 하며, 별도 요금이 발생할 수 있습니다.
  • -
  • Q12. 촬영한 데이터는 언제 받을 수 있나요?
    A. 영업일 기준 1~2일 이내 전달드립니다.
  • -
  • Q13. 녹화 시간에 제한이 있나요?
    A. 녹화 시간 제한은 없으며, 대관 시간 내 자유롭게 녹화하실 수 있습니다.
  • -
  • Q14. 추가 리타겟팅이나 수정 요청이 가능한가요?
    A. 가능합니다. 다만 추가 비용이 발생할 수 있습니다.
  • -
  • Q15. 탈의실이나 휴게 공간이 있나요?
    A. 네, 탈의실과 간단한 휴게 공간이 마련되어 있습니다. 빵, 햄버거, 커피 등의 간단한 취식이 가능합니다.
  • -
  • Q16. 몇 명까지 이용 가능한가요?
    A. 촬영 인원 최대 4명, 대기 인원 포함 최대 8명까지 수용 가능합니다.
  • -
  • Q17. 촬영 시 필요한 복장이나 준비물이 있나요?
    A. 기본적으로 준비물은 없지만, 안경은 반사로 인해 캡쳐에 오류가 발생할 수 있어 렌즈 착용을 권장드립니다.
  • -
  • Q18. 외부 팀이 장비만 사용할 수도 있나요?
    A. 장비만 사용하는 경우에도 사전 협의가 필요합니다. 기술 지원 여부에 따라 사용 조건이 달라질 수 있으므로 문의 바랍니다.
  • -
  • Q19. 주차는 가능한가요?
    A. 네, 가능합니다.
    기본 2시간 무료이며, 건물 내 시설(카페 등) 이용 시 추가 2시간, 최대 4시간 무료 주차가 가능합니다.
  • -
  • Q20. 동물이나 아동도 촬영이 가능한가요?
    A. 안전 및 장비 보호를 위해 동물 및 아동 출연은 현재 불가합니다.
  • -
  • Q21. 스튜디오 내부에서 자체 촬영을 해도 되나요?
    A. 사전 문의 시 내부 촬영은 일시적으로 허용될 수 있습니다. 촬영 목적에 따라 협의가 필요합니다.
  • -
+
+
+
+ +
+
+
+
+ +
+
+
+

최첨단 모션캡쳐 솔루션

+

버추얼 콘텐츠 제작을 위한 완벽한 환경

+
+ +
+
+
+
🎬
+
+

OptiTrack 카메라 시스템

+

28대의 고성능 광학식 카메라로 정밀한 모션 트래킹

+
+ +
+
+
👤
+
+

전신 & 페이셜 캡쳐

+

몸 전체 움직임과 얼굴 표정까지 실시간 캡쳐

+
+ +
+
+
🎮
+
+

실시간 스트리밍

+

서비스 준비중 (곧 출시 예정)

+
+ +
+
+
🛠️
+
+

전문 기술 지원

+

숙련된 오퍼레이터의 실시간 서포트

+
+
+
+
+ + +
+
+
+

주요 활용 분야

+

다양한 크리에이티브 프로젝트를 지원합니다

+
+ + + + +
+
+ + +
+
+
+

스튜디오 공간

+

최적의 모션캡쳐 환경을 제공합니다

+
+ +
+
+ 밍글 스튜디오 메인 모션캡쳐 공간 - 8m x 7m x 2.6m 규모의 OptiTrack 카메라 28대 설치 +
+

메인 캡쳐 공간

+

8m x 7m x 2.6m 볼륨

+
+
+
+
+ 밍글 스튜디오 컨트롤룸 - 전문 오퍼레이터가 실시간 모니터링하는 공간 +
+

컨트롤룸

+
+
+
+ 밍글 스튜디오 프라이빗 모션캡쳐 공간 - 개인 및 소규모 촬영 전용 공간 +
+

프라이빗 공간

+
+
+
+
+ + +
+
+ + +
+
+
+

포트폴리오

+

밍글 스튜디오에서 제작된 콘텐츠

+
+ +
+
+
+ +
+

모션캡쳐 포트폴리오

+
+
+
+ +
+

Shorts 콘텐츠

+
+
+ + +
+
+ + + +
+
+
+

궁금한 점이 있으신가요?

+

자주 묻는 질문을 확인하시거나 직접 문의해주세요

+
+ + +
+
+ + +
+
+
+

지금 바로 시작하세요

+

+ 최첨단 모션캡쳐 시스템으로 여러분의 창작 비전을 실현해보세요 +

+ + +
+ 📧 minglestudio.mocap@gmail.com + 📍 인천 부평구 주부토로 236, 인천테크노밸리 +
+
+
+ + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/index_backup.html b/index_backup.html new file mode 100644 index 0000000..de72222 --- /dev/null +++ b/index_backup.html @@ -0,0 +1,1303 @@ + + + + + + 밍글 스튜디오 - 모션캡쳐 창작 스튜디오 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+

밍글스튜디오
MINGLE STUDIO

+

기술과 창의력 열정이 한데 섞여 새로운 가치가 만들어지는 공간

+ 회사 소개 보기 +
+
+ 밍글 스튜디오 로고 +
+
+
+ + +
+
+
+

About

+
+

회사명: 밍글 스튜디오 (mingle studio)  |  설립일: 2025년 7월 15일

+

슬로건: "모두가 어우러진 즐거운 창작공간"

+

의미: Mingle Studio는 기술자와 크리에이터 그리고 시청자가 함께 어우러지는 버추얼 콘텐츠 제작 공간입니다. 최첨단 광학식 모션캡처 기술로 버추얼 캐릭터의 살아 숨쉬는 감정과 움직임을 담아 새로운 세대의 디지털 퍼포먼스를 실현합니다.

+
+
+
+

회사 소개

+

밍글 스튜디오는 창작자와 기술, 사람과 사람 사이의 '어우러짐'을 통해 새로운 콘텐츠를 만들어가는 모션 캡쳐 기반의 창작 공간입니다.
설립 이후, 누구나 편하게 사용 가능한 스튜디오 대관 서비스를 중심으로 버추얼 콘텐츠 제작 환경을 제공합니다.

+
+
+

연혁 / 타임라인

+ + + + + + +
날짜이벤트
2025년 7월 15일밍글 스튜디오 회사 설립
2025년 8월 1일밍글 스튜디오 오픈
+
+
+

Team

+

각 분야의 전문가들이 함께 협업하며 콘텐츠 제작을 지원합니다.

+
+
+
+

김희진 (JAYJAY)

+
대표 / 3D 아티스트
+
배경/리소스 제작, 인사 및 프로젝트 관리
+
+
+

김광진 (KINDNICK)

+
CTO / 테크니컬 디렉터
+
스튜디오 전체 기술 운영, 모션캡쳐 장비 관리, 음향 시스템, 엔진 프로그래밍 등
+
+
+

이승민 (YAMO)

+
CCO / 콘텐츠 디렉터
+
캡쳐 디렉팅, 배우 모션 클린업, 카메라 무빙, 퍼포먼스 연출 등
+
+
+
+
+ +
+
+
+

주요 서비스 소개

+
+ + +
+

서비스 항목 및 요금

+ + + + + + + + + + + + + + + + + + + + + + + + + +
서비스 항목설명요금
모션캡쳐 스튜디오 대관 + • 28대의 광학식 카메라 시스템 (OptiTrack)
+ • 모션캡쳐 수트 및 장갑 지원 (Rokoko Glove)
+ • 스튜디오 면적: 8m(가로) x 7m(세로) x 2.6m(높이)
+ • 실시간 모니터링 장비 보유
+ • 전신 및 페이셜 모션캡쳐 가능
+ • 동시 이용가능 인원: 최대 4인
+ • 모션 녹화 파일 제공
+ • 실시간 오퍼레이팅 지원 +
+ 시간당 220,000원
+ (VAT 포함)
+ 최소 이용: 2시간

+ 인원 요금:
+ • 기본 인원: 2인
+ • 추가 인원: +110,000원/시간당 +
모션 리타겟팅모션 데이터의 리타겟팅 지원별도 문의
(프로젝트별 견적)
실시간 스트리밍실시간 스트리밍 서비스준비중
+
+ + +
+

서비스 이용 안내

+ +

1) 스튜디오 대관 절차

+
+
+ 이메일 문의 + + 담당자 확인 및 세부사항 협의 + + 전액 결제 + + 예약 확정 +
+
+ + 📅 네이버 예약 바로가기 +

※ 네이버 플레이스를 통해 실시간 일정 확인 및 예약이 가능합니다

+
+ + +
+ +

2) 예약 안내

+
    +
  • 스튜디오 예약은 이용 희망일로부터 최소 2주 전에 신청하시는 것을 권장합니다.
  • +
  • 예약 확정 후 고객의 사정으로 인한 예약 취소 시 일정 기준에 따른 위약금이 발생합니다.
  • +
+ +

3) 취소 환불 규정

+ + + + + + + + + + + + + + + + + + + + + + + + + +
취소 시점환불 비율
예약일로부터 7일 전100% 환불
예약일로부터 3일 전70% 환불
예약일로부터 1일 전50% 환불
당일 취소환불 불가
+ +

4) 방문 안내

+
    +
  • 본 촬영 전 모션캡쳐 수트 착용 등의 준비시간이 소요되므로 촬영예정 시간 최소 30분 전에 방문 부탁드립니다. (준비시간은 이용시간에 포함되지 않습니다.)
  • +
  • 안경, 귀걸이 등 반사가 잘 되는 재질의 악세사리는 촬영 시 가급적 착용을 자제하여 주시기 바랍니다.
  • +
+
+ + +
+

스튜디오 이용 시 유의사항

+
    +
  • 스튜디오 내 모든 장비 및 설비는 소중히 다루어 주시기를 부탁드립니다.
  • +
  • 모션캡쳐 장비이용이 익숙하지 않으신 경우 사전에 운영진의 안내를 받으시거나 도움을 요청해 주세요. 정성껏 도와드리겠습니다.
  • +
  • 쾌적한 촬영환경과 장비 보호를 위해 촬영공간 내 음식물 반입 및 섭취를 지양해 주시기 바랍니다.
  • +
  • 대여 중 고객님의 고의 또는 과실로 인한 장비의 훼손 또는 분실이 발생한 경우, 수리 또는 교체에 필요한 비용이 청구될 수 있습니다.
  • +
+
+
+
+ + +
+
+
+

Portfolio

+

밍글 스튜디오에서 제작하거나 협업한 영상 콘텐츠는 YouTube 링크를 통해 확인하실 수 있습니다.

+
+ +
+
+ + + + + + + + + + +
+
+
+

Contact

+

예약 문의 또는 협업 제안은 언제든지 이메일로 연락주세요.

+
+
+ 이메일: minglestudio.mocap@gmail.com
+ 연락처: 010-9288-9190
+ 주소: (21330) 인천광역시 부평구 주부토로 236
+ 인천테크노밸리 A동 B105호
+
+ 오시는 길
+ - 인천 7호선 갈산역 하차 → 도보 약 7분 거리
+ - 건물 내 지하 주차 가능 (※ 2시간 무료) +
+ +
+
+
+ + +
+
+
+

FAQ – 자주 묻는 질문

+
+
    +
  • Q1. 스튜디오 대관은 어떻게 예약하나요?
    A. 이메일 문의를 통해 예약하실 수 있습니다.
    📧 minglestudio.mocap@gmail.com

    + 📅 네이버 예약 바로가기
    +

    ※ 네이버 플레이스를 통해 실시간 일정 확인 및 예약이 가능합니다

    + + +
  • +
  • Q2. 최소 대관 시간은 어떻게 되나요?
    A. 최소 대관은 2시간부터 가능합니다.
  • +
  • Q3. 대관은 얼마나 전에 예약해야 하나요?
    A. 최소 2주 전에 연락주시면 원활하게 준비가 가능합니다.
  • +
  • Q4. 현장 결제가 가능한가요?
    A. 네, 가능합니다.
  • +
  • Q5. 세금계산서 발행이 가능한가요?
    A. 네, 사업자용 세금계산서 발행 가능합니다.
  • +
  • Q6. 예약금 제도와 환불 규정이 있나요?
    A. 아래는 환불 규정입니다:
    취소 시점환불 비율
    예약일로부터 7일 전100% 환불
    예약일로부터 3일 전70% 환불
    예약일로부터 1일 전50% 환불
    당일 취소환불 불가
  • +
  • Q7. 모션 캡쳐 데이터는 어떤 형식으로 제공되나요?
    A. FBX, ANIM 포맷으로 제공되며, 문의 시 세부사항 안내해드립니다.
  • +
  • Q8. 리타겟팅도 함께 제공되나요?
    A. 기본 리타겟팅이 포함되어 있으며, 추가적인 클린업/후처리는 별도 견적 협의 후 제공됩니다.
  • +
  • Q9. 실시간 미리보기나 스트리밍이 가능한가요?
    A. 실시간 미리보기는 가능하며, 실시간 스트리밍은 지원 예정입니다.
  • +
  • Q10. 장비 사용이 익숙하지 않아도 괜찮을까요?
    A. 스튜디오에는 담당 인력이 배치되어 있어 장비 세팅 및 사용을 지원해드립니다.
  • +
  • Q11. 얼굴 캡쳐나 음성 녹음도 가능한가요?
    A. 가능합니다. 다만 예약 시 미리 요청해주셔야 하며, 별도 요금이 발생할 수 있습니다.
  • +
  • Q12. 촬영한 데이터는 언제 받을 수 있나요?
    A. 영업일 기준 1~2일 이내 전달드립니다.
  • +
  • Q13. 녹화 시간에 제한이 있나요?
    A. 녹화 시간 제한은 없으며, 대관 시간 내 자유롭게 녹화하실 수 있습니다.
  • +
  • Q14. 추가 리타겟팅이나 수정 요청이 가능한가요?
    A. 가능합니다. 다만 추가 비용이 발생할 수 있습니다.
  • +
  • Q15. 탈의실이나 휴게 공간이 있나요?
    A. 네, 탈의실과 간단한 휴게 공간이 마련되어 있습니다. 빵, 햄버거, 커피 등의 간단한 취식이 가능합니다.
  • +
  • Q16. 몇 명까지 이용 가능한가요?
    A. 촬영 인원 최대 4명, 대기 인원 포함 최대 8명까지 수용 가능합니다.
  • +
  • Q17. 촬영 시 필요한 복장이나 준비물이 있나요?
    A. 기본적으로 준비물은 없지만, 안경은 반사로 인해 캡쳐에 오류가 발생할 수 있어 렌즈 착용을 권장드립니다.
  • +
  • Q18. 외부 팀이 장비만 사용할 수도 있나요?
    A. 장비만 사용하는 경우에도 사전 협의가 필요합니다. 기술 지원 여부에 따라 사용 조건이 달라질 수 있으므로 문의 바랍니다.
  • +
  • Q19. 주차는 가능한가요?
    A. 네, 가능합니다.
    기본 2시간 무료이며, 건물 내 시설(카페 등) 이용 시 추가 2시간, 최대 4시간 무료 주차가 가능합니다.
  • +
  • Q20. 동물이나 아동도 촬영이 가능한가요?
    A. 안전 및 장비 보호를 위해 동물 및 아동 출연은 현재 불가합니다.
  • +
  • Q21. 스튜디오 내부에서 자체 촬영을 해도 되나요?
    A. 사전 문의 시 내부 촬영은 일시적으로 허용될 수 있습니다. 촬영 목적에 따라 협의가 필요합니다.
  • +
+
+
+ + + + \ No newline at end of file diff --git a/index_new.html b/index_new.html new file mode 100644 index 0000000..36d9306 --- /dev/null +++ b/index_new.html @@ -0,0 +1,164 @@ + + + + + + 밍글 스튜디오 - 모션캡쳐 창작 스튜디오 + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+
+
+

+ 모션캡쳐로 만드는
+ 무한한 창작의 세계 +

+

+ 최첨단 OptiTrack 시스템과 전문 장비를 갖춘
+ 밍글 스튜디오에서 여러분의 상상을 현실로 만들어보세요 +

+ +
+
+ +
+
+
+
+ + +
+
+
+

왜 밍글 스튜디오인가?

+

최고의 장비와 전문성으로 여러분의 프로젝트를 지원합니다

+
+
+
+
🎬
+

최첨단 OptiTrack 시스템

+

28대의 고성능 카메라로 구성된 전문 모션캡쳐 시스템

+
+
+
🏢
+

넓은 캡쳐 공간

+

8m x 8m x 3.5m의 여유로운 모션캡쳐 볼륨

+
+
+
💼
+

합리적인 가격

+

시간당 22만원(VAT 포함)의 투명한 요금제

+
+
+
🎯
+

전신 & 페이셜 캡쳐

+

몸 전체와 얼굴 표정까지 정밀하게 캡쳐 가능

+
+
+
🛠️
+

전문 기술 지원

+

숙련된 오퍼레이터의 기술 지원 서비스

+
+
+
📍
+

접근성 좋은 위치

+

인천테크노밸리 ITAVERSE 내 위치

+
+
+
+
+ + +
+
+

프로젝트를 시작할 준비가 되셨나요?

+

+ 밍글 스튜디오와 함께 여러분의 창작 비전을 실현해보세요 +

+ +
+
+ + +
+
+
+

제공 서비스

+

다양한 분야에서 활용 가능한 모션캡쳐 솔루션

+
+
+
+

🎮 게임 개발

+

캐릭터 애니메이션 및 모션 데이터 제작

+
+
+

🎬 영상 제작

+

VFX, 버추얼 프로덕션 지원

+
+
+

📱 메타버스 콘텐츠

+

버추얼 아바타 및 VTuber 제작

+
+
+

🏃 스포츠 분석

+

동작 분석 및 퍼포먼스 개선

+
+
+ +
+
+ + +
+
+

문의 및 예약

+
+

이메일: minglestudio@naver.com

+

위치: 인천광역시 연수구 컨벤시아대로 69, ITAVERSE 101동 701-1호

+

운영시간: 평일 09:00 - 18:00

+
+ 예약 문의하기 +
+
+ + + + + + + + + \ No newline at end of file diff --git a/js/common.js b/js/common.js new file mode 100644 index 0000000..6de5122 --- /dev/null +++ b/js/common.js @@ -0,0 +1,332 @@ +// ======================================== +// 공통 JavaScript 모듈 +// ======================================== + +// DOM 로드 완료 후 실행 +document.addEventListener('DOMContentLoaded', function() { + showPageLoading(); + initializeNavigation(); + setActiveNavLink(); + loadComponents(); + initLazyLoading(); + hidePageLoading(); +}); + +// ======================================== +// 컴포넌트 로드 함수 +// ======================================== +async function loadComponents() { + // Header 로드 + const headerPlaceholder = document.getElementById('header-placeholder'); + if (headerPlaceholder) { + try { + const response = await fetch('components/header.html'); + const html = await response.text(); + headerPlaceholder.innerHTML = html; + initializeNavigation(); // 헤더 로드 후 네비게이션 초기화 + } catch (error) { + console.error('Error loading header:', error); + } + } + + // Footer 로드 + const footerPlaceholder = document.getElementById('footer-placeholder'); + if (footerPlaceholder) { + try { + const response = await fetch('components/footer.html'); + const html = await response.text(); + footerPlaceholder.innerHTML = html; + } catch (error) { + console.error('Error loading footer:', error); + } + } +} + +// ======================================== +// 네비게이션 기능 +// ======================================== +function initializeNavigation() { + const hamburger = document.querySelector('.hamburger'); + const navMenu = document.querySelector('.nav-menu'); + + if (hamburger && navMenu) { + hamburger.addEventListener('click', function() { + hamburger.classList.toggle('active'); + navMenu.classList.toggle('active'); + }); + + // 네비게이션 링크 클릭 시 모바일 메뉴 닫기 + document.querySelectorAll('.nav-link').forEach(link => { + link.addEventListener('click', () => { + hamburger.classList.remove('active'); + navMenu.classList.remove('active'); + }); + }); + } + + // 스크롤 시 네비게이션 바 스타일 변경 + let lastScroll = 0; + window.addEventListener('scroll', () => { + const navbar = document.querySelector('.navbar'); + const currentScroll = window.pageYOffset; + + if (navbar) { + if (currentScroll > 100) { + navbar.style.boxShadow = '0 2px 20px rgba(0, 0, 0, 0.1)'; + } else { + navbar.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.05)'; + } + } + + lastScroll = currentScroll; + }); +} + +// ======================================== +// 현재 페이지 네비게이션 링크 활성화 +// ======================================== +function setActiveNavLink() { + const currentPath = window.location.pathname; + const navLinks = document.querySelectorAll('.nav-link'); + + navLinks.forEach(link => { + const linkPath = link.getAttribute('href'); + if (currentPath === linkPath || + (currentPath === '/' && linkPath === '/') || + (currentPath.includes(linkPath) && linkPath !== '/')) { + link.classList.add('active'); + } else { + link.classList.remove('active'); + } + }); +} + +// ======================================== +// 스크롤 애니메이션 +// ======================================== +function initScrollAnimations() { + const observerOptions = { + threshold: 0.1, + rootMargin: '0px 0px -100px 0px' + }; + + const observer = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + entry.target.classList.add('animate-in'); + } + }); + }, observerOptions); + + // 애니메이션 대상 요소 관찰 + document.querySelectorAll('.animate-on-scroll').forEach(el => { + observer.observe(el); + }); +} + +// ======================================== +// 유틸리티 함수 +// ======================================== + +// 이메일 유효성 검사 +function isValidEmail(email) { + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + return emailRegex.test(email); +} + +// 알림 표시 +function showNotification(message, type = 'info') { + // 기존 알림 제거 + const existingNotification = document.querySelector('.notification'); + if (existingNotification) { + existingNotification.remove(); + } + + // 새 알림 생성 + const notification = document.createElement('div'); + notification.className = `notification notification-${type}`; + notification.textContent = message; + + // 스타일 적용 + notification.style.cssText = ` + position: fixed; + top: 80px; + right: 20px; + padding: 1rem 2rem; + border-radius: 10px; + color: white; + font-weight: 600; + z-index: 10000; + transform: translateX(400px); + transition: transform 0.3s ease; + `; + + // 타입별 배경색 + const bgColors = { + success: '#10b981', + error: '#ef4444', + warning: '#f59e0b', + info: '#3b82f6' + }; + + notification.style.backgroundColor = bgColors[type] || bgColors.info; + document.body.appendChild(notification); + + // 애니메이션 + setTimeout(() => { + notification.style.transform = 'translateX(0)'; + }, 100); + + // 자동 제거 + setTimeout(() => { + notification.style.transform = 'translateX(400px)'; + setTimeout(() => { + if (notification.parentNode) { + notification.remove(); + } + }, 300); + }, 3000); +} + +// 디바운스 함수 +function debounce(func, wait) { + let timeout; + return function executedFunction(...args) { + const later = () => { + clearTimeout(timeout); + func(...args); + }; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + }; +} + +// 스로틀 함수 +function throttle(func, limit) { + let inThrottle; + return function(...args) { + if (!inThrottle) { + func.apply(this, args); + inThrottle = true; + setTimeout(() => inThrottle = false, limit); + } + }; +} + +// ======================================== +// Lazy Loading for YouTube iframes +// ======================================== +function initLazyLoading() { + // YouTube iframe lazy loading + const lazyIframes = document.querySelectorAll('iframe[data-src]'); + + if ('IntersectionObserver' in window) { + const iframeObserver = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + const iframe = entry.target; + iframe.src = iframe.dataset.src; + iframe.removeAttribute('data-src'); + iframeObserver.unobserve(iframe); + } + }); + }, { + rootMargin: '50px' + }); + + lazyIframes.forEach(iframe => { + iframeObserver.observe(iframe); + }); + } else { + // Fallback for older browsers + lazyIframes.forEach(iframe => { + iframe.src = iframe.dataset.src; + iframe.removeAttribute('data-src'); + }); + } + + // Image lazy loading (if any) + const lazyImages = document.querySelectorAll('img[data-src]'); + + if ('IntersectionObserver' in window && lazyImages.length > 0) { + const imageObserver = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + const img = entry.target; + img.src = img.dataset.src; + img.classList.remove('lazy'); + imageObserver.unobserve(img); + } + }); + }, { + rootMargin: '50px' + }); + + lazyImages.forEach(img => { + imageObserver.observe(img); + }); + } +} + +// ======================================== +// Export 함수들 (다른 스크립트에서 사용 가능) +// ======================================== +// ======================================== +// 로딩 상태 관리 +// ======================================== +function showPageLoading() { + // 페이지 로딩 오버레이가 이미 있는지 확인 + if (document.getElementById('pageLoadingOverlay')) return; + + const loadingOverlay = document.createElement('div'); + loadingOverlay.id = 'pageLoadingOverlay'; + loadingOverlay.className = 'loading-overlay'; + loadingOverlay.innerHTML = ` +
+
페이지를 불러오는 중...
+ `; + document.body.appendChild(loadingOverlay); +} + +function hidePageLoading() { + const loadingOverlay = document.getElementById('pageLoadingOverlay'); + if (loadingOverlay) { + setTimeout(() => { + loadingOverlay.style.opacity = '0'; + setTimeout(() => { + if (loadingOverlay.parentNode) { + loadingOverlay.remove(); + } + }, 150); + }, 100); // 최소 0.1초 표시 + } +} + +function showComponentLoading(element, text = '로딩 중...') { + element.innerHTML = ` +
+
+
${text}
+
+ `; +} + +function hideComponentLoading(element, content) { + element.innerHTML = content; +} + +// ======================================== +// Export 함수들 (다른 스크립트에서 사용 가능) +// ======================================== +window.commonUtils = { + showNotification, + isValidEmail, + debounce, + throttle, + initScrollAnimations, + initLazyLoading, + showPageLoading, + hidePageLoading, + showComponentLoading, + hideComponentLoading +}; \ No newline at end of file diff --git a/js/contact.js b/js/contact.js new file mode 100644 index 0000000..519ed8a --- /dev/null +++ b/js/contact.js @@ -0,0 +1,372 @@ +// ======================================== +// Contact 페이지 전용 JavaScript +// ======================================== + +document.addEventListener('DOMContentLoaded', function() { + initContactForm(); + initModal(); + initMap(); + initFormValidation(); +}); + +// 연락처 폼 초기화 +function initContactForm() { + const form = document.getElementById('contactForm'); + + if (form) { + form.addEventListener('submit', handleFormSubmit); + + // 실시간 유효성 검사 + const inputs = form.querySelectorAll('input, select, textarea'); + inputs.forEach(input => { + input.addEventListener('blur', validateField); + input.addEventListener('input', clearFieldError); + }); + + // 전화번호 자동 포맷팅 + const phoneInput = document.getElementById('phone'); + if (phoneInput) { + phoneInput.addEventListener('input', formatPhoneNumber); + } + + // 리셋 버튼 확인 + const resetBtn = form.querySelector('button[type="reset"]'); + if (resetBtn) { + resetBtn.addEventListener('click', handleFormReset); + } + } +} + +// 폼 제출 처리 +async function handleFormSubmit(e) { + e.preventDefault(); + + const form = e.target; + const submitBtn = form.querySelector('button[type="submit"]'); + + // 유효성 검사 + if (!validateForm(form)) { + showNotification('입력 정보를 확인해 주세요.', 'error'); + return; + } + + // 제출 버튼 비활성화 + const originalText = submitBtn.textContent; + submitBtn.textContent = '전송 중...'; + submitBtn.disabled = true; + + try { + // 폼 데이터 수집 + const formData = new FormData(form); + const data = Object.fromEntries(formData); + + // 실제 서버 전송 (현재는 시뮬레이션) + await submitContactForm(data); + + // 성공 메시지 + showNotification('문의가 성공적으로 전송되었습니다. 빠른 시일 내에 연락드리겠습니다.', 'success'); + form.reset(); + + } catch (error) { + console.error('Form submission error:', error); + showNotification('전송 중 오류가 발생했습니다. 다시 시도해 주세요.', 'error'); + } finally { + // 버튼 복원 + submitBtn.textContent = originalText; + submitBtn.disabled = false; + } +} + +// 서버 전송 시뮬레이션 +async function submitContactForm(data) { + // 실제 구현 시 서버 API 호출 + return new Promise((resolve, reject) => { + setTimeout(() => { + // 90% 확률로 성공 + if (Math.random() > 0.1) { + resolve({ success: true, message: '전송 완료' }); + } else { + reject(new Error('서버 오류')); + } + }, 2000); + }); +} + +// 폼 리셋 처리 +function handleFormReset(e) { + const confirmed = confirm('입력한 내용이 모두 삭제됩니다. 계속하시겠습니까?'); + if (!confirmed) { + e.preventDefault(); + } else { + // 에러 메시지 제거 + const errorElements = document.querySelectorAll('.field-error'); + errorElements.forEach(el => el.remove()); + + // 필드 에러 스타일 제거 + const fields = document.querySelectorAll('.form-group input, .form-group select, .form-group textarea'); + fields.forEach(field => field.classList.remove('error')); + } +} + +// 폼 유효성 검사 +function validateForm(form) { + let isValid = true; + + // 필수 필드 검사 + const requiredFields = form.querySelectorAll('[required]'); + requiredFields.forEach(field => { + if (!validateField({ target: field })) { + isValid = false; + } + }); + + // 이메일 형식 검사 + const emailField = form.querySelector('#email'); + if (emailField && emailField.value && !isValidEmail(emailField.value)) { + showFieldError(emailField, '올바른 이메일 형식을 입력해 주세요.'); + isValid = false; + } + + // 전화번호 형식 검사 + const phoneField = form.querySelector('#phone'); + if (phoneField && phoneField.value && !isValidPhone(phoneField.value)) { + showFieldError(phoneField, '올바른 전화번호 형식을 입력해 주세요.'); + isValid = false; + } + + return isValid; +} + +// 개별 필드 유효성 검사 +function validateField(e) { + const field = e.target; + const value = field.value.trim(); + + // 기존 에러 메시지 제거 + clearFieldError(e); + + // 필수 필드 검사 + if (field.required && !value) { + showFieldError(field, '필수 입력 항목입니다.'); + return false; + } + + // 이메일 형식 검사 + if (field.type === 'email' && value && !isValidEmail(value)) { + showFieldError(field, '올바른 이메일 형식을 입력해 주세요.'); + return false; + } + + // 전화번호 형식 검사 + if (field.type === 'tel' && value && !isValidPhone(value)) { + showFieldError(field, '올바른 전화번호 형식을 입력해 주세요.'); + return false; + } + + return true; +} + +// 필드 에러 표시 +function showFieldError(field, message) { + field.classList.add('error'); + + const errorEl = document.createElement('div'); + errorEl.className = 'field-error'; + errorEl.textContent = message; + errorEl.style.color = '#ef4444'; + errorEl.style.fontSize = '0.875rem'; + errorEl.style.marginTop = '0.25rem'; + + field.parentNode.appendChild(errorEl); +} + +// 필드 에러 제거 +function clearFieldError(e) { + const field = e.target; + field.classList.remove('error'); + + const errorEl = field.parentNode.querySelector('.field-error'); + if (errorEl) { + errorEl.remove(); + } +} + +// 이메일 유효성 검사 +function isValidEmail(email) { + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + return emailRegex.test(email); +} + +// 전화번호 유효성 검사 +function isValidPhone(phone) { + const phoneRegex = /^[0-9-+\s()]+$/; + return phoneRegex.test(phone) && phone.replace(/[^0-9]/g, '').length >= 10; +} + +// 전화번호 자동 포맷팅 +function formatPhoneNumber(e) { + let value = e.target.value.replace(/[^0-9]/g, ''); + + if (value.length >= 11) { + // 01X-XXXX-XXXX 형태 + value = value.replace(/(\d{3})(\d{4})(\d{4})/, '$1-$2-$3'); + } else if (value.length >= 7) { + // 01X-XXX-XXXX 또는 01X-XXXX-XXX 형태 + value = value.replace(/(\d{3})(\d{3,4})(\d{0,4})/, '$1-$2-$3'); + } else if (value.length >= 3) { + // 01X-XXX 형태 + value = value.replace(/(\d{3})(\d{0,4})/, '$1-$2'); + } + + e.target.value = value; +} + +// 알림 메시지 표시 +function showNotification(message, type = 'info') { + // 기존 알림 제거 + const existingNotification = document.querySelector('.notification'); + if (existingNotification) { + existingNotification.remove(); + } + + // 새 알림 생성 + const notification = document.createElement('div'); + notification.className = `notification notification-${type}`; + notification.innerHTML = ` + ${message} + + `; + + // 스타일 설정 + Object.assign(notification.style, { + position: 'fixed', + top: '20px', + right: '20px', + padding: '1rem 1.5rem', + borderRadius: '8px', + boxShadow: '0 4px 15px rgba(0, 0, 0, 0.15)', + zIndex: '9999', + maxWidth: '400px', + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + gap: '1rem' + }); + + // 타입별 색상 + const colors = { + success: { bg: '#10b981', color: 'white' }, + error: { bg: '#ef4444', color: 'white' }, + info: { bg: '#3b82f6', color: 'white' } + }; + + const color = colors[type] || colors.info; + notification.style.backgroundColor = color.bg; + notification.style.color = color.color; + + // 닫기 버튼 스타일 + const closeBtn = notification.querySelector('.notification-close'); + Object.assign(closeBtn.style, { + background: 'none', + border: 'none', + color: 'inherit', + fontSize: '1.5rem', + cursor: 'pointer', + padding: '0', + lineHeight: '1' + }); + + // 닫기 기능 + closeBtn.addEventListener('click', () => notification.remove()); + + // DOM에 추가 + document.body.appendChild(notification); + + // 5초 후 자동 제거 + setTimeout(() => { + if (notification.parentNode) { + notification.remove(); + } + }, 5000); +} + +// 모달 초기화 +function initModal() { + const modal = document.getElementById('privacyModal'); + const privacyLink = document.querySelector('.privacy-link'); + const closeBtn = modal?.querySelector('.modal-close'); + + if (privacyLink && modal) { + privacyLink.addEventListener('click', function(e) { + e.preventDefault(); + modal.classList.add('active'); + document.body.style.overflow = 'hidden'; + }); + } + + if (closeBtn && modal) { + closeBtn.addEventListener('click', function() { + modal.classList.remove('active'); + document.body.style.overflow = ''; + }); + } + + if (modal) { + modal.addEventListener('click', function(e) { + if (e.target === modal) { + modal.classList.remove('active'); + document.body.style.overflow = ''; + } + }); + } + + // ESC 키로 모달 닫기 + document.addEventListener('keydown', function(e) { + if (e.key === 'Escape' && modal?.classList.contains('active')) { + modal.classList.remove('active'); + document.body.style.overflow = ''; + } + }); +} + +// 지도 초기화 +function initMap() { + // HTML에 이미 정적으로 정보가 표시되어 있으므로 + // JavaScript로 덮어쓸 필요가 없음 + // 지도 기능은 외부 링크(네이버 지도, 구글 맵)를 통해 제공 + console.log('Map links are ready'); +} + + +// 폼 유효성 검사 초기화 +function initFormValidation() { + // CSS로 에러 스타일 정의 + const style = document.createElement('style'); + style.textContent = ` + .form-group input.error, + .form-group select.error, + .form-group textarea.error { + border-color: #ef4444 !important; + box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.1) !important; + } + + .field-error { + animation: fadeIn 0.3s ease; + } + + @keyframes fadeIn { + from { opacity: 0; transform: translateY(-5px); } + to { opacity: 1; transform: translateY(0); } + } + + .notification { + animation: slideIn 0.3s ease; + } + + @keyframes slideIn { + from { transform: translateX(100%); opacity: 0; } + to { transform: translateX(0); opacity: 1; } + } + `; + document.head.appendChild(style); +} \ No newline at end of file diff --git a/js/gallery.js b/js/gallery.js new file mode 100644 index 0000000..930d3fb --- /dev/null +++ b/js/gallery.js @@ -0,0 +1,266 @@ +// ======================================== +// Gallery 페이지 전용 JavaScript +// ======================================== + +document.addEventListener('DOMContentLoaded', function() { + initGallery(); + initLightbox(); + initGalleryAnimations(); +}); + +// 갤러리 초기화 +function initGallery() { + const galleryItems = document.querySelectorAll('.gallery-item'); + + galleryItems.forEach((item, index) => { + const img = item.querySelector('.gallery-img'); + + // 이미지 클릭 시 라이트박스 열기 + img.addEventListener('click', () => openLightbox(index)); + + // 이미지 로딩 에러 처리 + img.addEventListener('error', function() { + this.src = 'images/placeholder.jpg'; + this.alt = '이미지를 불러올 수 없습니다'; + }); + + // 레이지 로딩 구현 + if ('IntersectionObserver' in window) { + const imageObserver = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + const img = entry.target; + img.src = img.dataset.src || img.src; + img.classList.remove('lazy'); + imageObserver.unobserve(img); + } + }); + }); + + if (img.dataset.src) { + imageObserver.observe(img); + } + } + }); +} + +// 라이트박스 기능 +let currentImageIndex = 0; +const galleryImages = document.querySelectorAll('.gallery-img'); + +function initLightbox() { + // 라이트박스 HTML 생성 + const lightboxHTML = ` + + `; + + document.body.insertAdjacentHTML('beforeend', lightboxHTML); + + // ESC 키로 라이트박스 닫기 + document.addEventListener('keydown', function(e) { + if (e.key === 'Escape') closeLightbox(); + if (e.key === 'ArrowLeft') previousImage(); + if (e.key === 'ArrowRight') nextImage(); + }); + + // 배경 클릭으로 라이트박스 닫기 + document.getElementById('lightbox').addEventListener('click', function(e) { + if (e.target === this) closeLightbox(); + }); +} + +function openLightbox(index) { + currentImageIndex = index; + const lightbox = document.getElementById('lightbox'); + const lightboxImg = document.getElementById('lightbox-img'); + const lightboxCaption = document.getElementById('lightbox-caption'); + + const currentImg = galleryImages[index]; + const caption = currentImg.closest('.gallery-item').querySelector('.gallery-caption'); + + lightboxImg.src = currentImg.src; + lightboxImg.alt = currentImg.alt; + lightboxCaption.textContent = caption ? caption.textContent : currentImg.alt; + + lightbox.classList.add('active'); + document.body.style.overflow = 'hidden'; +} + +function closeLightbox() { + const lightbox = document.getElementById('lightbox'); + lightbox.classList.remove('active'); + document.body.style.overflow = ''; +} + +function nextImage() { + currentImageIndex = (currentImageIndex + 1) % galleryImages.length; + openLightbox(currentImageIndex); +} + +function previousImage() { + currentImageIndex = (currentImageIndex - 1 + galleryImages.length) % galleryImages.length; + openLightbox(currentImageIndex); +} + +// 갤러리 애니메이션 +function initGalleryAnimations() { + const galleryItems = document.querySelectorAll('.gallery-item'); + + // Intersection Observer를 사용한 애니메이션 + const observerOptions = { + threshold: 0.1, + rootMargin: '50px 0px' + }; + + const observer = new IntersectionObserver((entries) => { + entries.forEach((entry, index) => { + if (entry.isIntersecting) { + setTimeout(() => { + entry.target.style.opacity = '1'; + entry.target.style.transform = 'translateY(0)'; + }, index * 100); + observer.unobserve(entry.target); + } + }); + }, observerOptions); + + galleryItems.forEach(item => { + item.style.opacity = '0'; + item.style.transform = 'translateY(30px)'; + item.style.transition = 'all 0.6s cubic-bezier(0.4, 0, 0.2, 1)'; + observer.observe(item); + }); +} + +// 갤러리 필터 기능 (향후 확장용) +function initGalleryFilters() { + const filterButtons = document.querySelectorAll('.filter-btn'); + const galleryItems = document.querySelectorAll('.gallery-item'); + + filterButtons.forEach(btn => { + btn.addEventListener('click', function() { + // 활성 버튼 업데이트 + filterButtons.forEach(b => b.classList.remove('active')); + this.classList.add('active'); + + const filter = this.dataset.filter; + + galleryItems.forEach(item => { + if (filter === 'all' || item.dataset.category === filter) { + item.style.display = 'block'; + setTimeout(() => { + item.style.opacity = '1'; + item.style.transform = 'scale(1)'; + }, 10); + } else { + item.style.opacity = '0'; + item.style.transform = 'scale(0.8)'; + setTimeout(() => { + item.style.display = 'none'; + }, 300); + } + }); + }); + }); +} + +// 이미지 프리로딩 +function preloadImages() { + galleryImages.forEach(img => { + const imagePreload = new Image(); + imagePreload.src = img.src; + }); +} + +// 갤러리 검색 기능 (향후 확장용) +function initGallerySearch() { + const searchInput = document.getElementById('gallery-search'); + const galleryItems = document.querySelectorAll('.gallery-item'); + + if (searchInput) { + searchInput.addEventListener('input', function() { + const searchTerm = this.value.toLowerCase(); + + galleryItems.forEach(item => { + const caption = item.querySelector('.gallery-caption'); + const alt = item.querySelector('.gallery-img').alt; + const text = (caption ? caption.textContent : '') + ' ' + alt; + + if (text.toLowerCase().includes(searchTerm)) { + item.style.display = 'block'; + } else { + item.style.display = 'none'; + } + }); + }); + } +} + +// 이미지 로딩 상태 표시 +function showGalleryLoading() { + const loading = document.querySelector('.gallery-loading'); + if (loading) { + loading.style.display = 'block'; + } +} + +function hideGalleryLoading() { + const loading = document.querySelector('.gallery-loading'); + if (loading) { + loading.style.display = 'none'; + } +} + +// 갤러리 그리드 리사이즈 최적화 +let resizeTimeout; +window.addEventListener('resize', function() { + clearTimeout(resizeTimeout); + resizeTimeout = setTimeout(function() { + // 갤러리 그리드 재조정 로직 + const galleryGrid = document.querySelector('.gallery-grid'); + if (galleryGrid) { + galleryGrid.style.opacity = '0.8'; + setTimeout(() => { + galleryGrid.style.opacity = '1'; + }, 100); + } + }, 250); +}); + +// 터치 이벤트 지원 (모바일) +let touchStartX = 0; +let touchEndX = 0; + +document.addEventListener('touchstart', function(e) { + if (document.getElementById('lightbox').classList.contains('active')) { + touchStartX = e.changedTouches[0].screenX; + } +}); + +document.addEventListener('touchend', function(e) { + if (document.getElementById('lightbox').classList.contains('active')) { + touchEndX = e.changedTouches[0].screenX; + handleSwipe(); + } +}); + +function handleSwipe() { + const swipeThreshold = 50; + const diff = touchStartX - touchEndX; + + if (Math.abs(diff) > swipeThreshold) { + if (diff > 0) { + nextImage(); // 왼쪽으로 스와이프 = 다음 이미지 + } else { + previousImage(); // 오른쪽으로 스와이프 = 이전 이미지 + } + } +} \ No newline at end of file diff --git a/js/main.js b/js/main.js new file mode 100644 index 0000000..b5f9db2 --- /dev/null +++ b/js/main.js @@ -0,0 +1,128 @@ +// ======================================== +// 메인 페이지 전용 JavaScript +// ======================================== + +document.addEventListener('DOMContentLoaded', function() { + initMainPageAnimations(); + initCounterAnimation(); +}); + +// ======================================== +// 메인 페이지 애니메이션 +// ======================================== +function initMainPageAnimations() { + // Hero 섹션 애니메이션 + const heroElements = document.querySelectorAll('.hero-title, .hero-description, .hero-buttons'); + heroElements.forEach((el, index) => { + el.style.opacity = '0'; + el.style.transform = 'translateY(30px)'; + + setTimeout(() => { + el.style.transition = 'all 0.8s ease'; + el.style.opacity = '1'; + el.style.transform = 'translateY(0)'; + }, 100 * (index + 1)); + }); + + // Feature 카드 애니메이션 + const observerOptions = { + threshold: 0.2, + rootMargin: '0px 0px -50px 0px' + }; + + const observer = new IntersectionObserver((entries) => { + entries.forEach((entry, index) => { + if (entry.isIntersecting) { + setTimeout(() => { + entry.target.style.opacity = '1'; + entry.target.style.transform = 'translateY(0)'; + }, index * 100); + observer.unobserve(entry.target); + } + }); + }, observerOptions); + + // Feature 카드 초기 상태 설정 및 관찰 + document.querySelectorAll('.feature-card').forEach(card => { + card.style.opacity = '0'; + card.style.transform = 'translateY(30px)'; + card.style.transition = 'all 0.6s ease'; + observer.observe(card); + }); + + // Service 아이템 애니메이션 + document.querySelectorAll('.service-item').forEach(item => { + item.style.opacity = '0'; + item.style.transform = 'translateX(-30px)'; + item.style.transition = 'all 0.6s ease'; + observer.observe(item); + }); +} + +// ======================================== +// 카운터 애니메이션 (선택적) +// ======================================== +function initCounterAnimation() { + const counters = document.querySelectorAll('.counter'); + + if (counters.length === 0) return; + + const animateCounter = (counter) => { + const target = parseInt(counter.getAttribute('data-target')); + const duration = 2000; // 2초 + const increment = target / (duration / 16); // 60fps 기준 + let current = 0; + + const updateCounter = () => { + current += increment; + if (current < target) { + counter.textContent = Math.floor(current); + requestAnimationFrame(updateCounter); + } else { + counter.textContent = target; + } + }; + + updateCounter(); + }; + + const counterObserver = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + animateCounter(entry.target); + counterObserver.unobserve(entry.target); + } + }); + }, { threshold: 0.5 }); + + counters.forEach(counter => { + counterObserver.observe(counter); + }); +} + +// ======================================== +// 패럴랙스 효과 (선택적) +// ======================================== +window.addEventListener('scroll', () => { + const scrolled = window.pageYOffset; + const parallaxElements = document.querySelectorAll('.parallax'); + + parallaxElements.forEach(el => { + const speed = el.getAttribute('data-speed') || 0.5; + el.style.transform = `translateY(${scrolled * speed}px)`; + }); +}); + +// ======================================== +// 마우스 호버 효과 +// ======================================== +document.querySelectorAll('.feature-card, .service-item').forEach(card => { + card.addEventListener('mouseenter', function(e) { + const rect = this.getBoundingClientRect(); + const x = e.clientX - rect.left; + const y = e.clientY - rect.top; + + this.style.setProperty('--mouse-x', `${x}px`); + this.style.setProperty('--mouse-y', `${y}px`); + }); +}); \ No newline at end of file diff --git a/js/portfolio.js b/js/portfolio.js new file mode 100644 index 0000000..2754e7e --- /dev/null +++ b/js/portfolio.js @@ -0,0 +1,478 @@ +// ======================================== +// Portfolio 페이지 전용 JavaScript +// ======================================== + +document.addEventListener('DOMContentLoaded', function() { + initVideoLazyLoading(); + initPortfolioAnimations(); + initVideoInteractions(); + initYouTubeAPI(); +}); + +// 비디오 레이지 로딩 초기화 +function initVideoLazyLoading() { + const videoWrappers = document.querySelectorAll('.video-wrapper'); + + // Intersection Observer를 사용한 레이지 로딩 + const observerOptions = { + threshold: 0.1, + rootMargin: '50px 0px' + }; + + const observer = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + loadVideo(entry.target); + observer.unobserve(entry.target); + } + }); + }, observerOptions); + + videoWrappers.forEach(wrapper => { + observer.observe(wrapper); + + // 로딩 상태 표시 + if (!wrapper.querySelector('.video-loading')) { + const loadingDiv = document.createElement('div'); + loadingDiv.className = 'video-loading'; + loadingDiv.textContent = '비디오 로딩 중...'; + wrapper.appendChild(loadingDiv); + } + }); +} + +// 비디오 로딩 +function loadVideo(wrapper) { + const iframe = wrapper.querySelector('iframe'); + if (iframe && iframe.dataset.src) { + // 실제 src 설정 + iframe.src = iframe.dataset.src; + + // 로딩 완료 처리 + iframe.addEventListener('load', function() { + wrapper.classList.add('loaded'); + const loadingDiv = wrapper.querySelector('.video-loading'); + if (loadingDiv) { + loadingDiv.remove(); + } + }); + + // 에러 처리 + iframe.addEventListener('error', function() { + const loadingDiv = wrapper.querySelector('.video-loading'); + if (loadingDiv) { + loadingDiv.textContent = '비디오를 로드할 수 없습니다'; + loadingDiv.style.color = '#ef4444'; + } + }); + } else { + // 이미 src가 설정된 경우 + wrapper.classList.add('loaded'); + const loadingDiv = wrapper.querySelector('.video-loading'); + if (loadingDiv) { + loadingDiv.remove(); + } + } +} + +// 포트폴리오 애니메이션 초기화 +function initPortfolioAnimations() { + // 비디오 카드 애니메이션 + const videoCards = document.querySelectorAll('.video-card'); + const observerOptions = { + threshold: 0.1, + rootMargin: '30px 0px' + }; + + const cardObserver = new IntersectionObserver((entries) => { + entries.forEach((entry, index) => { + if (entry.isIntersecting) { + setTimeout(() => { + entry.target.style.opacity = '1'; + entry.target.style.transform = 'translateY(0)'; + }, index * 150); + cardObserver.unobserve(entry.target); + } + }); + }, observerOptions); + + videoCards.forEach(card => { + card.style.opacity = '0'; + card.style.transform = 'translateY(30px)'; + card.style.transition = 'all 0.6s cubic-bezier(0.4, 0, 0.2, 1)'; + cardObserver.observe(card); + }); + + // 기술 특징 애니메이션 + const techFeatures = document.querySelectorAll('.tech-feature'); + techFeatures.forEach((feature, index) => { + feature.style.opacity = '0'; + feature.style.transform = 'translateY(30px)'; + feature.style.transition = 'all 0.6s ease'; + + setTimeout(() => { + feature.style.opacity = '1'; + feature.style.transform = 'translateY(0)'; + }, 200 * (index + 1)); + }); + + // YouTube 채널 카드 애니메이션 + const channelCard = document.querySelector('.youtube-channel-card'); + if (channelCard) { + channelCard.style.opacity = '0'; + channelCard.style.transform = 'scale(0.95)'; + channelCard.style.transition = 'all 0.8s ease'; + + setTimeout(() => { + channelCard.style.opacity = '1'; + channelCard.style.transform = 'scale(1)'; + }, 300); + } +} + +// 비디오 상호작용 초기화 +function initVideoInteractions() { + const videoCards = document.querySelectorAll('.video-card'); + + videoCards.forEach(card => { + const iframe = card.querySelector('iframe'); + const videoInfo = card.querySelector('.video-info'); + + // 카드 호버 효과 + card.addEventListener('mouseenter', function() { + if (videoInfo) { + videoInfo.style.transform = 'translateY(-5px)'; + videoInfo.style.transition = 'transform 0.3s ease'; + } + }); + + card.addEventListener('mouseleave', function() { + if (videoInfo) { + videoInfo.style.transform = 'translateY(0)'; + } + }); + + // 비디오 클릭 시 전체화면 효과 + if (iframe) { + iframe.addEventListener('click', function() { + this.style.transform = 'scale(1.02)'; + setTimeout(() => { + this.style.transform = 'scale(1)'; + }, 200); + }); + } + }); + + // 태그 클릭 기능 + const tags = document.querySelectorAll('.tag'); + tags.forEach(tag => { + tag.addEventListener('click', function() { + const tagName = this.textContent.toLowerCase(); + filterByTag(tagName); + }); + + // 호버 효과 + tag.addEventListener('mouseenter', function() { + this.style.transform = 'scale(1.1)'; + this.style.cursor = 'pointer'; + }); + + tag.addEventListener('mouseleave', function() { + this.style.transform = 'scale(1)'; + }); + }); +} + +// 태그별 필터링 +function filterByTag(tagName) { + const videoCards = document.querySelectorAll('.video-card'); + + videoCards.forEach(card => { + const tags = card.querySelectorAll('.tag'); + const hasTag = Array.from(tags).some(tag => + tag.textContent.toLowerCase().includes(tagName) + ); + + if (hasTag) { + card.style.display = 'block'; + card.style.animation = 'fadeIn 0.5s ease'; + } else { + card.style.opacity = '0.3'; + card.style.animation = 'fadeOut 0.5s ease'; + } + }); + + // 3초 후 필터 해제 + setTimeout(() => { + videoCards.forEach(card => { + card.style.display = 'block'; + card.style.opacity = '1'; + card.style.animation = 'fadeIn 0.5s ease'; + }); + }, 3000); +} + +// YouTube API 초기화 +function initYouTubeAPI() { + // YouTube IFrame API 로드 + if (!window.YT) { + const tag = document.createElement('script'); + tag.src = 'https://www.youtube.com/iframe_api'; + const firstScriptTag = document.getElementsByTagName('script')[0]; + firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); + } + + // API 준비 완료 시 실행 + window.onYouTubeIframeAPIReady = function() { + initYouTubePlayers(); + }; +} + +// YouTube 플레이어 초기화 +function initYouTubePlayers() { + const youtubeIframes = document.querySelectorAll('iframe[src*="youtube.com"]'); + const players = []; + + youtubeIframes.forEach((iframe, index) => { + const videoId = extractVideoId(iframe.src); + if (videoId) { + // 기존 iframe 교체 + const playerDiv = document.createElement('div'); + playerDiv.id = `youtube-player-${index}`; + iframe.parentNode.replaceChild(playerDiv, iframe); + + // YouTube 플레이어 생성 + const player = new YT.Player(playerDiv.id, { + height: '100%', + width: '100%', + videoId: videoId, + playerVars: { + modestbranding: 1, + rel: 0, + showinfo: 0, + controls: 1, + autoplay: 0 + }, + events: { + onReady: onPlayerReady, + onStateChange: onPlayerStateChange, + onError: onPlayerError + } + }); + + players.push(player); + } + }); + + return players; +} + +// YouTube 비디오 ID 추출 +function extractVideoId(url) { + const match = url.match(/embed\/([^?&]+)/); + return match ? match[1] : null; +} + +// 플레이어 준비 완료 +function onPlayerReady(event) { + console.log('YouTube player ready'); + + // 플레이어 컨테이너에 로딩 완료 클래스 추가 + const playerElement = event.target.getIframe(); + const wrapper = playerElement.closest('.video-wrapper'); + if (wrapper) { + wrapper.classList.add('loaded'); + const loadingDiv = wrapper.querySelector('.video-loading'); + if (loadingDiv) { + loadingDiv.remove(); + } + } +} + +// 플레이어 상태 변경 +function onPlayerStateChange(event) { + const playerElement = event.target.getIframe(); + const videoCard = playerElement.closest('.video-card'); + + if (event.data === YT.PlayerState.PLAYING) { + // 재생 시작 시 다른 비디오 일시정지 + pauseOtherVideos(event.target); + + // 재생 중 표시 + if (videoCard) { + videoCard.classList.add('playing'); + } + + // 재생 추적 (선택사항) + trackVideoPlay(event.target); + + } else if (event.data === YT.PlayerState.PAUSED || event.data === YT.PlayerState.ENDED) { + // 일시정지/종료 시 + if (videoCard) { + videoCard.classList.remove('playing'); + } + } +} + +// 플레이어 오류 처리 +function onPlayerError(event) { + console.error('YouTube player error:', event.data); + const playerElement = event.target.getIframe(); + const wrapper = playerElement.closest('.video-wrapper'); + + if (wrapper) { + const errorDiv = document.createElement('div'); + errorDiv.className = 'video-error'; + errorDiv.innerHTML = '비디오를 로드할 수 없습니다
네트워크 연결을 확인해주세요'; + errorDiv.style.cssText = ` + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + text-align: center; + color: #ef4444; + font-size: 1rem; + z-index: 10; + `; + wrapper.appendChild(errorDiv); + } +} + +// 다른 비디오 일시정지 +function pauseOtherVideos(currentPlayer) { + if (window.youtubePlayers) { + window.youtubePlayers.forEach(player => { + if (player !== currentPlayer && player.pauseVideo) { + player.pauseVideo(); + } + }); + } +} + +// 비디오 재생 추적 +function trackVideoPlay(player) { + if (typeof gtag !== 'undefined') { + const videoTitle = player.getVideoData().title; + gtag('event', 'video_play', { + event_category: 'Portfolio', + event_label: videoTitle, + value: 1 + }); + } +} + +// 비디오 공유 기능 +function shareVideo(videoUrl, title) { + if (navigator.share) { + navigator.share({ + title: title || '밍글 스튜디오 포트폴리오', + url: videoUrl + }); + } else { + // 클립보드에 복사 + navigator.clipboard.writeText(videoUrl).then(() => { + showNotification('비디오 링크가 클립보드에 복사되었습니다.', 'success'); + }); + } +} + +// 포트폴리오 통계 +function getPortfolioStats() { + const longformVideos = document.querySelectorAll('.longform-grid .video-card').length; + const shortsVideos = document.querySelectorAll('.shorts-grid .video-card').length; + const broadcastVideos = document.querySelectorAll('.broadcast-grid .video-card').length; + + return { + longform: longformVideos, + shorts: shortsVideos, + broadcasts: broadcastVideos, + total: longformVideos + shortsVideos + broadcastVideos + }; +} + +// 알림 메시지 표시 +function showNotification(message, type = 'info') { + const existingNotification = document.querySelector('.notification'); + if (existingNotification) { + existingNotification.remove(); + } + + const notification = document.createElement('div'); + notification.className = `notification notification-${type}`; + notification.innerHTML = ` + ${message} + + `; + + Object.assign(notification.style, { + position: 'fixed', + top: '20px', + right: '20px', + padding: '1rem 1.5rem', + borderRadius: '8px', + boxShadow: '0 4px 15px rgba(0, 0, 0, 0.15)', + zIndex: '9999', + maxWidth: '400px', + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + gap: '1rem' + }); + + const colors = { + success: { bg: '#10b981', color: 'white' }, + error: { bg: '#ef4444', color: 'white' }, + info: { bg: '#3b82f6', color: 'white' } + }; + + const color = colors[type] || colors.info; + notification.style.backgroundColor = color.bg; + notification.style.color = color.color; + + const closeBtn = notification.querySelector('.notification-close'); + Object.assign(closeBtn.style, { + background: 'none', + border: 'none', + color: 'inherit', + fontSize: '1.5rem', + cursor: 'pointer', + padding: '0', + lineHeight: '1' + }); + + closeBtn.addEventListener('click', () => notification.remove()); + document.body.appendChild(notification); + + setTimeout(() => { + if (notification.parentNode) { + notification.remove(); + } + }, 5000); +} + +// CSS 애니메이션 정의 +const style = document.createElement('style'); +style.textContent = ` + @keyframes fadeIn { + from { opacity: 0; transform: translateY(20px); } + to { opacity: 1; transform: translateY(0); } + } + + @keyframes fadeOut { + from { opacity: 1; transform: translateY(0); } + to { opacity: 0.3; transform: translateY(10px); } + } + + .video-card.playing { + box-shadow: 0 0 20px rgba(255, 136, 0, 0.3); + border: 2px solid rgba(255, 136, 0, 0.5); + } + + .tag:hover { + transform: scale(1.1); + background: var(--primary-color); + color: var(--text-white); + cursor: pointer; + } +`; +document.head.appendChild(style); \ No newline at end of file diff --git a/js/qna.js b/js/qna.js new file mode 100644 index 0000000..38af18b --- /dev/null +++ b/js/qna.js @@ -0,0 +1,516 @@ +// ======================================== +// FAQ 페이지 전용 JavaScript +// ======================================== + +document.addEventListener('DOMContentLoaded', function() { + initFAQ(); + initSearch(); + initCategories(); + initAnimations(); + initEmailForm(); +}); + +// FAQ 기능 초기화 +function initFAQ() { + const faqItems = document.querySelectorAll('.faq-item'); + + faqItems.forEach(item => { + const question = item.querySelector('.faq-question'); + const toggle = item.querySelector('.faq-toggle'); + const answer = item.querySelector('.faq-answer'); + + if (question && toggle && answer) { + question.addEventListener('click', () => toggleFAQ(item)); + + // 키보드 접근성 + question.addEventListener('keydown', (e) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + toggleFAQ(item); + } + }); + + // 포커스 가능하도록 설정 + question.setAttribute('tabindex', '0'); + question.setAttribute('role', 'button'); + question.setAttribute('aria-expanded', 'false'); + } + }); +} + +// FAQ 아이템 토글 +function toggleFAQ(item) { + const isActive = item.classList.contains('active'); + const answer = item.querySelector('.faq-answer'); + const question = item.querySelector('.faq-question'); + + if (isActive) { + // 닫기 + item.classList.remove('active'); + question.setAttribute('aria-expanded', 'false'); + answer.style.maxHeight = '0'; + } else { + // 다른 모든 FAQ 닫기 (아코디언 효과) + document.querySelectorAll('.faq-item.active').forEach(activeItem => { + if (activeItem !== item) { + activeItem.classList.remove('active'); + activeItem.querySelector('.faq-question').setAttribute('aria-expanded', 'false'); + activeItem.querySelector('.faq-answer').style.maxHeight = '0'; + } + }); + + // 현재 FAQ 열기 + item.classList.add('active'); + question.setAttribute('aria-expanded', 'true'); + + // 정확한 높이 계산을 위해 잠시 보이게 한 후 측정 + answer.style.maxHeight = 'none'; + answer.style.overflow = 'visible'; + const height = answer.scrollHeight; + answer.style.maxHeight = '0'; + answer.style.overflow = 'hidden'; + + // 애니메이션을 위해 약간의 지연 후 높이 설정 + setTimeout(() => { + answer.style.maxHeight = (height + 50) + 'px'; + }, 10); + + // 스크롤 애니메이션 + setTimeout(() => { + item.scrollIntoView({ + behavior: 'smooth', + block: 'nearest' + }); + }, 100); + } +} + +// 검색 기능 초기화 +function initSearch() { + const searchInput = document.getElementById('faqSearch'); + const searchBtn = document.querySelector('.search-btn'); + const suggestions = document.getElementById('searchSuggestions'); + + if (searchInput) { + let searchTimeout; + + searchInput.addEventListener('input', function() { + clearTimeout(searchTimeout); + searchTimeout = setTimeout(() => { + handleSearch(this.value.trim()); + updateSearchSuggestions(this.value.trim()); + }, 300); + }); + + searchInput.addEventListener('keydown', function(e) { + if (e.key === 'Enter') { + e.preventDefault(); + handleSearch(this.value.trim()); + hideSuggestions(); + } + }); + + // 검색 버튼 클릭 + if (searchBtn) { + searchBtn.addEventListener('click', () => { + handleSearch(searchInput.value.trim()); + hideSuggestions(); + }); + } + + // 클릭 외부 영역 시 제안 사항 숨기기 + document.addEventListener('click', function(e) { + if (!searchInput.contains(e.target) && !suggestions?.contains(e.target)) { + hideSuggestions(); + } + }); + } +} + +// 검색 처리 +function handleSearch(query) { + const faqItems = document.querySelectorAll('.faq-item'); + const noResults = document.querySelector('.no-results'); + let hasResults = false; + + if (!query) { + // 검색어가 없으면 모든 항목 표시 + faqItems.forEach(item => { + item.classList.remove('hidden'); + clearSearchHighlight(item); + }); + hideNoResults(); + return; + } + + const searchRegex = new RegExp(query, 'gi'); + + faqItems.forEach(item => { + const question = item.querySelector('.faq-question h3'); + const answer = item.querySelector('.faq-answer'); + const questionText = question.textContent; + const answerText = answer.textContent; + + // 검색어 매칭 확인 + const questionMatch = searchRegex.test(questionText); + const answerMatch = searchRegex.test(answerText); + + if (questionMatch || answerMatch) { + item.classList.remove('hidden'); + hasResults = true; + + // 검색어 하이라이트 + highlightSearchTerm(item, query); + + // 답변에 매칭되는 경우 자동으로 열기 + if (answerMatch && !questionMatch) { + toggleFAQ(item); + } + } else { + item.classList.add('hidden'); + clearSearchHighlight(item); + } + }); + + // 검색 결과가 없는 경우 + if (!hasResults) { + showNoResults(query); + } else { + hideNoResults(); + } +} + +// 검색어 하이라이트 +function highlightSearchTerm(item, term) { + const question = item.querySelector('.faq-question h3'); + const answer = item.querySelector('.faq-answer'); + + const highlightRegex = new RegExp(`(${term})`, 'gi'); + + // 질문 하이라이트 + const originalQuestionText = question.dataset.originalText || question.textContent; + question.dataset.originalText = originalQuestionText; + question.innerHTML = originalQuestionText.replace(highlightRegex, '$1'); + + // 답변 하이라이트 + const answerElements = answer.querySelectorAll('p, li'); + answerElements.forEach(el => { + const originalText = el.dataset.originalText || el.textContent; + el.dataset.originalText = originalText; + el.innerHTML = originalText.replace(highlightRegex, '$1'); + }); +} + +// 검색 하이라이트 제거 +function clearSearchHighlight(item) { + const question = item.querySelector('.faq-question h3'); + const answer = item.querySelector('.faq-answer'); + + // 질문 하이라이트 제거 + if (question.dataset.originalText) { + question.textContent = question.dataset.originalText; + delete question.dataset.originalText; + } + + // 답변 하이라이트 제거 + const answerElements = answer.querySelectorAll('p, li'); + answerElements.forEach(el => { + if (el.dataset.originalText) { + el.textContent = el.dataset.originalText; + delete el.dataset.originalText; + } + }); +} + +// 검색 제안사항 업데이트 +function updateSearchSuggestions(query) { + const suggestions = document.getElementById('searchSuggestions'); + if (!suggestions || !query || query.length < 2) { + hideSuggestions(); + return; + } + + // 미리 정의된 검색 키워드 + const searchKeywords = [ + '예약', '취소', '환불', '요금', '가격', '결제', + '장비', '모션캡쳐', '시간', '인원', '준비물', + '데이터', '파일', '형식', '스트리밍', '버튜버', + '주차', '위치', '견학', '투어', '방역', '코로나' + ]; + + const matchingKeywords = searchKeywords.filter(keyword => + keyword.includes(query) || query.includes(keyword) + ); + + if (matchingKeywords.length > 0) { + suggestions.innerHTML = matchingKeywords + .slice(0, 5) + .map(keyword => + `
${keyword}
` + ).join(''); + suggestions.classList.add('active'); + } else { + hideSuggestions(); + } +} + +// 제안사항 선택 +function selectSuggestion(keyword) { + const searchInput = document.getElementById('faqSearch'); + if (searchInput) { + searchInput.value = keyword; + handleSearch(keyword); + } + hideSuggestions(); +} + +// 제안사항 숨기기 +function hideSuggestions() { + const suggestions = document.getElementById('searchSuggestions'); + if (suggestions) { + suggestions.classList.remove('active'); + } +} + +// 검색 결과 없음 표시 +function showNoResults(query) { + let noResults = document.querySelector('.no-results'); + if (!noResults) { + noResults = document.createElement('div'); + noResults.className = 'no-results'; + noResults.innerHTML = ` +
🔍
+

검색 결과가 없습니다

+

"${query}"와 관련된 질문을 찾을 수 없습니다.

+

다른 키워드로 검색해보시거나 직접 문의해 주세요.

+ `; + document.querySelector('.faq-list').appendChild(noResults); + } else { + noResults.querySelector('p strong').textContent = `"${query}"`; + } + noResults.classList.add('active'); +} + +// 검색 결과 없음 숨기기 +function hideNoResults() { + const noResults = document.querySelector('.no-results'); + if (noResults) { + noResults.classList.remove('active'); + } +} + +// 카테고리 필터 초기화 +function initCategories() { + const categoryBtns = document.querySelectorAll('.category-btn'); + + categoryBtns.forEach(btn => { + btn.addEventListener('click', function() { + const category = this.dataset.category; + + // 활성 버튼 업데이트 + categoryBtns.forEach(b => b.classList.remove('active')); + this.classList.add('active'); + + // FAQ 필터링 + filterByCategory(category); + + // 검색 초기화 + const searchInput = document.getElementById('faqSearch'); + if (searchInput) { + searchInput.value = ''; + } + hideSuggestions(); + hideNoResults(); + }); + }); +} + +// 카테고리별 필터링 +function filterByCategory(category) { + const faqItems = document.querySelectorAll('.faq-item'); + + faqItems.forEach(item => { + // 모든 FAQ 닫기 + item.classList.remove('active'); + item.querySelector('.faq-answer').style.maxHeight = '0'; + item.querySelector('.faq-question').setAttribute('aria-expanded', 'false'); + + // 검색 하이라이트 제거 + clearSearchHighlight(item); + + if (category === 'all' || item.dataset.category === category) { + item.classList.remove('hidden'); + } else { + item.classList.add('hidden'); + } + }); + + // 페이지 상단으로 스크롤 + document.querySelector('.faq-list').scrollIntoView({ + behavior: 'smooth', + block: 'start' + }); +} + +// 애니메이션 초기화 +function initAnimations() { + // Intersection Observer를 사용한 스크롤 애니메이션 + const observerOptions = { + threshold: 0.1, + rootMargin: '50px 0px' + }; + + const observer = new IntersectionObserver((entries) => { + entries.forEach((entry, index) => { + if (entry.isIntersecting) { + setTimeout(() => { + entry.target.style.opacity = '1'; + entry.target.style.transform = 'translateY(0)'; + }, index * 100); + observer.unobserve(entry.target); + } + }); + }, observerOptions); + + // FAQ 아이템들에 초기 스타일 적용 및 관찰 시작 + const faqItems = document.querySelectorAll('.faq-item'); + faqItems.forEach(item => { + item.style.opacity = '0'; + item.style.transform = 'translateY(30px)'; + item.style.transition = 'all 0.6s cubic-bezier(0.4, 0, 0.2, 1)'; + observer.observe(item); + }); +} + +// URL 해시로 특정 FAQ 열기 +function openFAQByHash() { + const hash = window.location.hash.substring(1); + if (hash) { + const faqItem = document.querySelector(`[data-id="${hash}"]`); + if (faqItem) { + toggleFAQ(faqItem); + faqItem.scrollIntoView({ behavior: 'smooth', block: 'center' }); + } + } +} + +// 페이지 로드 시 해시 확인 +window.addEventListener('load', openFAQByHash); + +// FAQ 공유 기능 (선택사항) +function shareFAQ(faqId) { + const url = `${window.location.origin}${window.location.pathname}#${faqId}`; + + if (navigator.share) { + navigator.share({ + title: 'FAQ - 밍글 스튜디오', + url: url + }); + } else { + // 클립보드에 복사 + navigator.clipboard.writeText(url).then(() => { + showNotification('링크가 클립보드에 복사되었습니다.', 'success'); + }); + } +} + +// 알림 메시지 표시 (contact.js와 동일한 함수) +function showNotification(message, type = 'info') { + const existingNotification = document.querySelector('.notification'); + if (existingNotification) { + existingNotification.remove(); + } + + const notification = document.createElement('div'); + notification.className = `notification notification-${type}`; + notification.innerHTML = ` + ${message} + + `; + + Object.assign(notification.style, { + position: 'fixed', + top: '20px', + right: '20px', + padding: '1rem 1.5rem', + borderRadius: '8px', + boxShadow: '0 4px 15px rgba(0, 0, 0, 0.15)', + zIndex: '9999', + maxWidth: '400px', + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + gap: '1rem' + }); + + const colors = { + success: { bg: '#10b981', color: 'white' }, + error: { bg: '#ef4444', color: 'white' }, + info: { bg: '#3b82f6', color: 'white' } + }; + + const color = colors[type] || colors.info; + notification.style.backgroundColor = color.bg; + notification.style.color = color.color; + + const closeBtn = notification.querySelector('.notification-close'); + Object.assign(closeBtn.style, { + background: 'none', + border: 'none', + color: 'inherit', + fontSize: '1.5rem', + cursor: 'pointer', + padding: '0', + lineHeight: '1' + }); + + closeBtn.addEventListener('click', () => notification.remove()); + document.body.appendChild(notification); + + setTimeout(() => { + if (notification.parentNode) { + notification.remove(); + } + }, 5000); +} + +// 이메일 폼 초기화 +function initEmailForm() { + const emailBtn = document.getElementById('showEmailFormFAQ'); + const emailForm = document.getElementById('emailFormFAQ'); + + if (emailBtn && emailForm) { + emailBtn.addEventListener('click', function() { + if (emailForm.style.display === 'none' || !emailForm.style.display) { + emailForm.style.display = 'block'; + emailBtn.textContent = '📧 양식 숨기기'; + + // FAQ 답변 높이 재계산 + const faqItem = emailForm.closest('.faq-item'); + const answer = faqItem.querySelector('.faq-answer'); + if (faqItem.classList.contains('active')) { + // 높이 재계산을 위해 잠시 auto로 설정 + answer.style.maxHeight = 'none'; + const newHeight = answer.scrollHeight; + answer.style.maxHeight = (newHeight + 100) + 'px'; // 여유분 추가 + } + + setTimeout(() => { + emailForm.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); + }, 100); + } else { + emailForm.style.display = 'none'; + emailBtn.innerHTML = '📧 이메일 문의하기'; + + // FAQ 답변 높이 재계산 + const faqItem = emailForm.closest('.faq-item'); + const answer = faqItem.querySelector('.faq-answer'); + if (faqItem.classList.contains('active')) { + answer.style.maxHeight = 'none'; + const newHeight = answer.scrollHeight; + answer.style.maxHeight = (newHeight + 50) + 'px'; + } + } + }); + } +} \ No newline at end of file diff --git a/js/services.js b/js/services.js new file mode 100644 index 0000000..8f48f0c --- /dev/null +++ b/js/services.js @@ -0,0 +1,77 @@ +// ======================================== +// Services 페이지 전용 JavaScript +// ======================================== + +document.addEventListener('DOMContentLoaded', function() { + initEmailForm(); + initServiceAnimations(); +}); + +// 이메일 폼 토글 기능 +function initEmailForm() { + const showEmailBtn = document.getElementById('showEmailForm'); + const emailForm = document.getElementById('emailForm'); + + if (showEmailBtn && emailForm) { + showEmailBtn.addEventListener('click', function() { + if (emailForm.style.display === 'none' || !emailForm.style.display) { + emailForm.style.display = 'block'; + showEmailBtn.textContent = '📧 이메일 양식 닫기'; + emailForm.scrollIntoView({ behavior: 'smooth', block: 'center' }); + } else { + emailForm.style.display = 'none'; + showEmailBtn.innerHTML = '📧 이메일 문의하기'; + } + }); + } +} + +// 서비스 페이지 애니메이션 +function initServiceAnimations() { + // 프로세스 스텝 애니메이션 + const processSteps = document.querySelectorAll('.process-step'); + const observer = new IntersectionObserver((entries) => { + entries.forEach((entry, index) => { + if (entry.isIntersecting) { + setTimeout(() => { + entry.target.style.opacity = '1'; + entry.target.style.transform = 'translateY(0)'; + }, index * 200); + observer.unobserve(entry.target); + } + }); + }, { threshold: 0.3 }); + + processSteps.forEach(step => { + step.style.opacity = '0'; + step.style.transform = 'translateY(30px)'; + step.style.transition = 'all 0.6s ease'; + observer.observe(step); + }); + + // 장비 카드 애니메이션 + const equipmentCards = document.querySelectorAll('.equipment-card'); + equipmentCards.forEach((card, index) => { + card.style.opacity = '0'; + card.style.transform = 'translateY(30px)'; + card.style.transition = 'all 0.6s ease'; + + setTimeout(() => { + card.style.opacity = '1'; + card.style.transform = 'translateY(0)'; + }, 100 * (index + 1)); + }); +} + +// 테이블 행 하이라이트 +document.querySelectorAll('.services-table tbody tr').forEach(row => { + row.addEventListener('mouseenter', function() { + this.style.backgroundColor = 'rgba(255, 136, 0, 0.05)'; + }); + + row.addEventListener('mouseleave', function() { + if (!this.classList.contains('main-service')) { + this.style.backgroundColor = ''; + } + }); +}); \ No newline at end of file diff --git a/naver-site-verification.html b/naver-site-verification.html new file mode 100644 index 0000000..0df7a34 --- /dev/null +++ b/naver-site-verification.html @@ -0,0 +1,11 @@ + + + + + Naver Site Verification + + + +

밍글 스튜디오 - 네이버 웹마스터 도구 인증

+ + diff --git a/portfolio.html b/portfolio.html new file mode 100644 index 0000000..ee47561 --- /dev/null +++ b/portfolio.html @@ -0,0 +1,325 @@ + + + + + + 포트폴리오 - 밍글 스튜디오 + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+
+
+
📺
+
+

밍글 스튜디오 공식 채널

+

최신 모션캡쳐 콘텐츠와 제작 과정을 YouTube에서 확인하세요

+
+
+ + YouTube 채널 방문하기 + +
+
+
+ + +
+
+
+

Long-Form 콘텐츠

+

밍글 스튜디오의 주요 모션캡쳐 프로젝트

+
+ +
+ + +
+
+ +
+
+

「 QWER - 가짜아이돌 (FAKE IDOL) 」 COVER BY VENY 【CROA】

+

VENY가 커버한 QWER의 가짜아이돌

+
+ 커버 + CROA + VENY +
+
+
+ +
+
+ +
+
+

aesoopa 에숲파 'Black Mamba' MV

+

에숲파의 Black Mamba 뮤직비디오

+
+ MV + 에숲파 + Black Mamba +
+
+
+
+
+
+ + +
+
+
+

Shorts 콘텐츠

+

짧고 임팩트 있는 모션캡쳐 순간들

+
+ +
+
+
+ +
+
+

스ㅡㅡㅡㅡㅡㅡㅡ게 💕STARGAZERS CHALLENGE

+
+
+ +
+
+ +
+
+

🤎 곰이의 이세계 아이돌 - ELEVATE 챌린지 🤎

+
+
+ +
+
+ +
+
+

Memory 깡담비 #하이라이트 #shorts

+
+
+
+
+
+ + +
+
+
+

실시간 방송 예시

+

버튜버와 스트리머들의 실시간 모션캡쳐 방송

+
+ +
+
🔴
+
+

실시간 모션캡쳐 방송

+

밍글 스튜디오에서 진행되는 실시간 모션캡쳐 방송을 통해 고품질 버추얼 콘텐츠를 경험하세요

+
+
+ +
+
+
+ +
+
+

미르 첫 모캡 방송

+
+ SOOP + 미르 +
+
+
+ +
+
+ +
+
+

춤짱자매즈 모캡 합방 (w. 호발)

+
+ SOOP + 춤짱자매즈 +
+
+
+ +
+
+ +
+
+

치요 X 마늘 3D 모션캡쳐 합방

+
+ SOOP + 치요 & 마늘 +
+
+
+ +
+
+ +
+
+

뉴걸의 첫 모캡방송!

+

춤 못 추면 댄스방송 하면 안 되나요?

+
+ SOOP + 뉴걸 +
+
+
+
+
+
+ + +
+
+
+

기술적 특징

+

밍글 스튜디오 모션캡쳐의 핵심 기술

+
+ +
+
+
+

실시간 처리

+

28대 OptiTrack 카메라로 실시간 모션 데이터 처리

+
+ +
+
🎯
+

정밀 트래킹

+

전신과 페이셜 모션을 동시에 정밀 캡쳐

+
+ +
+
📡
+

스트리밍 서비스

+

현재 준비중 (곧 출시 예정)

+
+ +
+
🔄
+

다양한 포맷

+

FBX, ANIM 포맷으로 데이터 출력

+
+
+
+
+ + +
+
+

당신의 콘텐츠도 여기에

+

밍글 스튜디오와 함께 다음 포트폴리오의 주인공이 되어보세요

+ +
+
+ + + + + + + + + + + + \ No newline at end of file diff --git a/qna.html b/qna.html new file mode 100644 index 0000000..024bb7b --- /dev/null +++ b/qna.html @@ -0,0 +1,417 @@ + + + + + + 자주 묻는 질문 - 밍글 스튜디오 + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+ +
+
+ + +
+
+
+ + + + + + + +
+
+
+ + +
+
+
+ + +
+
+

스튜디오 대관은 어떻게 예약하나요?

+ + +
+
+

아래 방법으로 예약하실 수 있습니다:

+ +
+ +
+ + + +

최소 2주 전에 연락주시면 원활하게 준비가 가능합니다.

+
+
+ +
+
+

예약금 제도와 환불 규정이 있나요?

+ + +
+
+

아래는 환불 규정입니다:

+
+
+ 예약일로부터 7일 전 + 100% 환불 +
+
+ 예약일로부터 3일 전 + 70% 환불 +
+
+ 예약일로부터 1일 전 + 50% 환불 +
+
+ 당일 취소 + 환불 불가 +
+
+
+
+ +
+
+

최소 대관 시간은 어떻게 되나요?

+ + +
+
+

최소 대관은 2시간부터 가능합니다.

+

연장은 1시간 단위로 가능합니다.

+
+
+ +
+
+

대관은 얼마나 전에 예약해야 하나요?

+ + +
+
+

최소 2주 전에 연락주시면 원활하게 준비가 가능합니다.

+
+
+ +
+
+

현장 결제가 가능한가요?

+ + +
+
+

현장에서는 현금 결제 또는 계좌이체가 가능합니다.

+

카드 결제는 현장에서 불가능하니 참고해 주세요.

+

현금영수증 및 세금계산서 발행 가능합니다.

+
+
+ +
+
+

세금계산서 발행이 가능한가요?

+ + +
+
+

네, 사업자용 세금계산서 발행 가능합니다.

+
+
+ + +
+
+

어떤 모션캡쳐 장비를 사용하나요?

+ + +
+
+

밍글 스튜디오는 다음과 같은 전문 장비를 보유하고 있습니다:

+
    +
  • OptiTrack 카메라: 28대
  • +
  • 핸드 트래킹: 로코코 스마트 글러브 사용중
  • +
+
+
+ +
+
+

모션캡쳐 슈트는 제공되나요?

+ + +
+
+

네, 전문 모션캡쳐 슈트와 마커를 무료로 제공합니다.

+
    +
  • 다양한 사이즈 (S, M, L, XL) 보유
  • +
  • 위생적인 관리로 깔끔한 상태 유지
  • +
  • 개인 슈트 지참도 가능
  • +
  • 장갑, 헤드밴드 등 부속품 포함
  • +
+
+
+ +
+
+

몇 명까지 동시에 모션캡쳐가 가능한가요?

+ + +
+
+

최대 4명까지 동시 모션캡쳐가 가능합니다.

+

인원별 상세 정보:

+
    +
  • 1명: 최고 정밀도 캡쳐
  • +
  • 2명: 상호작용 장면 최적
  • +
  • 3-4명: 그룹 퍼포먼스 가능
  • +
+

인원이 많을수록 캡쳐 공간과 정확도에 제약이 있을 수 있습니다.

+
+
+ + +
+
+

스튜디오 대관 요금은 얼마인가요?

+ + +
+
+

스튜디오 대관 기본 요금은 다음과 같습니다:

+
+
+ 기본 대관 (2시간) + 220,000원 +
+
+ 연장 (1시간 단위) + 110,000원 +
+
+

* 부가세 포함, 운영진 지원비 포함

+
+
+ +
+
+

결제는 어떻게 하나요?

+ + +
+
+

다음과 같은 결제 방법을 지원합니다:

+
    +
  • 계좌이체: 예약 확정 후 24시간 내
  • +
  • 현금결제: 현장 결제 가능
  • +
  • 카드결제: 현장에서 불가능
  • +
  • 세금계산서: 사업자 고객 발행 가능
  • +
  • 현금영수증: 개인 고객 발행 가능
  • +
+

예약금(30%)은 예약 확정 시, 잔금(70%)은 촬영 당일 결제 가능합니다.

+
+
+ + +
+
+

촬영 준비물은 무엇이 필요한가요?

+ + +
+
+

기본적으로 다음과 같은 준비가 필요합니다:

+
    +
  • 복장: 몸에 딱 맞는 검은색 의상 (면 소재 선호)
  • +
  • 신발: 실내화 또는 양말
  • +
  • 머리: 긴 머리는 묶어주세요
  • +
  • 액세서리: 시계, 반지 등 제거
  • +
  • 메이크업: 진한 메이크업은 피해주세요
  • +
+

모션캡쳐 슈트와 마커는 스튜디오에서 제공합니다.

+
+
+ +
+
+

데이터는 어떤 형태로 받을 수 있나요?

+ + +
+
+

다음과 같은 형태의 데이터를 제공합니다:

+
    +
  • FBX 파일: Unity, Unreal Engine 호환
  • +
  • ANIM 파일: Unity Animator 직접 호환
  • +
  • MP4 영상: 참고용 영상
  • +
+

문의 시 세부사항을 안내해드리며, 클라우드를 통해 전달합니다.

+
+
+ + +
+
+

실시간 스트리밍이 가능한가요?

+ + +
+
+

실시간 스트리밍 서비스는 현재 준비중입니다.

+

서비스 준비가 완료되는 대로 안내해드리겠습니다.

+
+
+ + +
+
+

주차는 가능한가요?

+ + +
+
+

네, 주차가 가능합니다:

+
    +
  • 기본: 2시간 무료
  • +
  • 건물 내 시설 이용시: 추가 2시간, 최대 4시간 무료
  • +
  • 위치: 인천테크노밸리 건물 주차장
  • +
+
+
+ +
+
+

견학이나 시설 투어는 가능한가요?

+ + +
+
+

견학 및 투어는 미리 문의를 통해 가능 여부를 확인해야 합니다:

+
    +
  • 사전 문의: 필수 (스튜디오 사정에 따라 거절될 수 있음)
  • +
  • 문의처: minglestudio.mocap@gmail.com
  • +
  • 견학 시간: 승인 시 협의 (약 30분 소요)
  • +
  • 비용: 무료
  • +
+

스튜디오 운영 상황에 따라 견학이 제한될 수 있으니 양해 부탁드립니다.

+
+
+ + +
+
+
+ + +
+
+

원하는 답변을 찾지 못하셨나요?

+

궁금한 점이 있으시면 언제든지 문의해 주세요

+ +
+
+ + + + + + + + + + + + \ No newline at end of file diff --git a/robots.txt b/robots.txt index cb4f55d..1502c93 100644 --- a/robots.txt +++ b/robots.txt @@ -1,14 +1,29 @@ User-agent: * Allow: / -# Specifically allow Naver bot +# 네이버봇 특별 설정 User-agent: Yeti Allow: / +Crawl-delay: 1 -# Sitemap +# 중요한 페이지 우선순위 Sitemap: https://minglestudio.co.kr/sitemap.xml -# Disallow specific files and patterns -Disallow: /cgi-bin/ -Disallow: /tmp/ -Disallow: /private/ \ No newline at end of file +# 크롤링 제외할 파일/디렉토리 +Disallow: /js/ +Disallow: /css/ +Disallow: /*.js$ +Disallow: /*.css$ +Disallow: /components/ + +# 이미지 크롤링 허용 (포트폴리오 중요) +Allow: /Studio_Image/ +Allow: /mingle* +Allow: /*.jpg$ +Allow: /*.jpeg$ +Allow: /*.png$ +Allow: /*.webp$ +Allow: /*.gif$ + +# 검색엔진별 크롤링 속도 조절 +Crawl-delay: 1 diff --git a/services.html b/services.html new file mode 100644 index 0000000..5031f1f --- /dev/null +++ b/services.html @@ -0,0 +1,363 @@ + + + + + + 서비스 소개 - 밍글 스튜디오 + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+
+

주요 서비스 소개

+
+ + +
+
+

서비스 항목 및 요금

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
서비스 항목설명요금
+
+ 🎬 + 모션캡쳐 스튜디오 대관 +
+
+
    +
  • 28대의 광학식 카메라 시스템 (OptiTrack)
  • +
  • 모션캡쳐 수트 및 장갑 지원 (Rokoko Glove)
  • +
  • 스튜디오 면적: 8m(가로) x 7m(세로) x 2.6m(높이)
  • +
  • 실시간 모니터링 장비 보유
  • +
  • 전신 및 페이셜 모션캡쳐 가능
  • +
  • 동시 이용가능 인원: 최대 4인
  • +
  • 모션 녹화 파일 제공
  • +
  • 실시간 오퍼레이팅 지원
  • +
+
+
시간당 220,000원
+
(VAT 포함)
+
+ 최소 이용: 2시간

+ 인원 요금:
+ • 기본 인원: 2인
+ • 추가 인원: +110,000원/시간당 +
+
+
+ 🔄 + 모션 리타겟팅 +
+
모션 데이터의 리타겟팅 지원 +
별도 문의
+
(프로젝트별 견적)
+
+
+ 📺 + 실시간 스트리밍 +
+
실시간 스트리밍 서비스 +
준비중
+
+
+
+
+
+
+ + +
+
+
+

서비스 이용 안내

+
+ + +
+

스튜디오 대관 절차

+
+
+
1
+
+

이메일 문의

+

예약 양식을 작성하여 문의

+
+
+
+
+
2
+
+

담당자 확인 및 협의

+

세부사항 조율

+
+
+
+
+
3
+
+

전액 결제

+

결제 완료

+
+
+
+
+
4
+
+

예약 확정

+

최종 예약 완료

+
+
+
+ +
+ + + 📅 네이버 예약 바로가기 + +
+

※ 네이버 플레이스를 통해 실시간 일정 확인 및 예약이 가능합니다

+ + + +
+ + +
+
+

예약 안내

+
    +
  • 스튜디오 예약은 이용 희망일로부터 최소 2주 전에 신청하시는 것을 권장합니다.
  • +
  • 예약 확정 후 고객의 사정으로 인한 예약 취소 시 일정 기준에 따른 위약금이 발생합니다.
  • +
+
+ +
+

방문 안내

+
    +
  • 본 촬영 전 모션캡쳐 수트 착용 등의 준비시간이 소요되므로 촬영예정 시간 최소 30분 전에 방문 부탁드립니다. (준비시간은 이용시간에 포함되지 않습니다.)
  • +
  • 안경, 귀걸이 등 반사가 잘 되는 재질의 악세사리는 촬영 시 가급적 착용을 자제하여 주시기 바랍니다.
  • +
+
+
+ + +
+

취소 환불 규정

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
취소 시점환불 비율
예약일로부터 7일 전100% 환불
예약일로부터 3일 전70% 환불
예약일로부터 1일 전50% 환불
당일 취소환불 불가
+
+
+
+
+ + +
+
+
+

장비 및 시설

+

업계 최고 수준의 모션캡쳐 장비와 시설을 갖추고 있습니다

+
+ +
+
+
📹
+

OptiTrack 카메라 시스템

+

28대의 고해상도 광학식 카메라로 정밀한 모션 트래킹

+
+ +
+
🥽
+

모션캡쳐 수트

+

Rokoko Glove 포함 전신 모션캡쳐 장비 완비

+
+ +
+
💻
+

실시간 모니터링

+

실시간 모션 데이터 확인 및 즉시 피드백

+
+ +
+
📊
+

데이터 출력

+

FBX, ANIM 포맷으로 모션 데이터 파일 제공

+
+
+
+
+ + +
+
+

지금 바로 예약하세요

+

최고의 모션캡쳐 경험을 제공해드립니다

+ +
+
+ + + + + + + + + + + + \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index c328359..277773c 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -2,7 +2,50 @@ https://minglestudio.co.kr/ + 2024-12-13 weekly 1.0 - \ No newline at end of file + + https://minglestudio.co.kr/index.html + 2024-12-13 + weekly + 1.0 + + + https://minglestudio.co.kr/about.html + 2024-12-13 + monthly + 0.8 + + + https://minglestudio.co.kr/services.html + 2024-12-13 + monthly + 0.9 + + + https://minglestudio.co.kr/portfolio.html + 2024-12-13 + weekly + 0.8 + + + https://minglestudio.co.kr/gallery.html + 2024-12-13 + monthly + 0.7 + + + https://minglestudio.co.kr/contact.html + 2024-12-13 + monthly + 0.7 + + + https://minglestudio.co.kr/qna.html + 2024-12-13 + weekly + 0.6 + +