이미제

This commit is contained in:
2026-10-20 08:54:01 +09:00
parent eb99be1210
commit e0dcc8c2b0
113 changed files with 7214 additions and 965 deletions
+7 -3
View File
@@ -178,7 +178,7 @@ const handleSubmit = async () => {
try { try {
const currentUrl = typeof window !== 'undefined' ? window.location.href : '' const currentUrl = typeof window !== 'undefined' ? window.location.href : ''
await $fetch('/api/consult', { const res = await $fetch('/api/consult', {
method: 'POST', method: 'POST',
body: { body: {
studentName: form.value.studentName, studentName: form.value.studentName,
@@ -190,10 +190,14 @@ const handleSubmit = async () => {
url: currentUrl url: currentUrl
} }
}) })
if (res && res.success) {
submitted.value = true submitted.value = true
} else {
alert('상담 신청 접수 중 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.')
}
} catch (err) { } catch (err) {
console.error('상담 신청 전송:', err) console.error('상담 신청 전송 실패:', err)
submitted.value = true alert('상담 신청 접수 중 문제가 발생했습니다. 전화(010-5961-5807)로 문의해 주시기 바랍니다.')
} finally { } finally {
loading.value = false loading.value = false
} }
+783
View File
@@ -0,0 +1,783 @@
<template>
<section class="subject-gallery-section" aria-label="과목별 1:1 맞춤과외 갤러리">
<div class="gallery-container">
<!-- 섹션 헤더 -->
<div class="gallery-header">
<span class="gallery-badge">
<i class="fa-solid fa-sparkles mr-1"></i>
{{ regionDong ? `${regionDong} ` : '' }}과목별 1:1 전문 전담팀
</span>
<h2 class="gallery-title">
취약 과목을 1등급 전략 과목으로 역전시키는<br />
<strong>1:1 전담 과목별 클래스</strong>
</h2>
<p class="gallery-desc">
원하시는 과목 카드를 클릭하시면 1:1 맞춤 커리큘럼과 상세 안내를 페이지에서 크게 확인하실 수 있습니다.
</p>
</div>
<!-- 2 - 2 - 1 그리드 정렬 레이아웃 -->
<div class="subject-grid-221">
<div
v-for="(item, idx) in subjectList"
:key="item.name"
class="gallery-card"
:class="`card-item-${idx + 1}`"
@click="openModal(item)"
>
<div class="card-inner">
<div class="img-wrap">
<img
:src="item.image"
:alt="`${item.name} 1:1 맞춤 지도`"
class="subject-img"
loading="lazy"
/>
<span class="subject-tag">{{ item.tag }}</span>
<div class="zoom-overlay">
<span class="zoom-btn">
<i class="fa-solid fa-magnifying-glass-plus"></i>
<span>상세 보기</span>
</span>
</div>
</div>
<div class="card-info">
<div class="card-subject-name">
<span class="sub-name">{{ item.name }}</span>
<span class="sub-grade">{{ grade }}</span>
</div>
<p class="card-subject-desc">{{ item.desc }}</p>
<div class="card-action">
<span>자세히 보기 & 신청</span>
<i class="fa-solid fa-arrow-right"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 클릭 시 페이지에 크게 나오는 상세 모달 (Lightbox Modal) -->
<Teleport to="body">
<Transition name="modal-fade">
<div
v-if="selectedItem"
class="modal-backdrop"
@click.self="closeModal"
role="dialog"
aria-modal="true"
>
<div class="modal-card">
<!-- 닫기 버튼 -->
<button
type="button"
class="modal-close-btn"
@click="closeModal"
aria-label="닫기"
>
<i class="fa-solid fa-xmark"></i>
</button>
<div class="modal-grid">
<!-- 모달 좌측: 고해상도 생성 이미지 원본 -->
<div class="modal-img-col">
<img
:src="selectedItem.image"
:alt="`${selectedItem.name} 1:1 맞춤 과외`"
class="modal-main-img"
/>
<span class="modal-img-badge">{{ selectedItem.tag }}</span>
</div>
<!-- 모달 우측: 상세 설명 및 액션 버튼 -->
<div class="modal-content-col">
<div class="modal-header">
<span class="modal-pill">{{ regionDong || '관내' }} 1:1 밀착 코칭</span>
<h3 class="modal-title">
{{ selectedItem.name }}
<span class="text-sub">1:1 맞춤 마스터 클래스</span>
</h3>
<p class="modal-slogan">{{ selectedItem.slogan }}</p>
</div>
<div class="modal-points">
<div class="point-row" v-for="(pt, pIdx) in selectedItem.details" :key="pIdx">
<span class="point-num">0{{ pIdx + 1 }}</span>
<div>
<strong class="point-head">{{ pt.title }}</strong>
<p class="point-body">{{ pt.desc }}</p>
</div>
</div>
</div>
<!-- 모달 하단 액션 버튼 그룹 -->
<div class="modal-actions">
<button
type="button"
class="btn-modal-apply"
@click="applyWithSubject(selectedItem.name)"
>
<i class="fa-solid fa-paper-plane mr-2"></i>
<span>{{ selectedItem.name }} 무료 상담 신청하기</span>
</button>
<button
type="button"
class="btn-modal-link"
@click="goToSubjectPage(selectedItem.subjectKey)"
>
<span>전용 페이지 이동</span>
<i class="fa-solid fa-chevron-right ml-1"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</Transition>
</Teleport>
</section>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
const props = defineProps({
regionDong: {
type: String,
default: ''
},
grade: {
type: String,
default: '중·고등'
},
currentSubject: {
type: String,
default: ''
}
})
const router = useRouter()
// 5대 핵심 과목 (2 2 1 순서 배치)
const subjectList = [
// 1행: 수학, 영어
{
name: '수학과외',
subjectKey: 'math',
tag: '인기 1위',
image: '/img/수학과외.png',
desc: '개념 구멍 추적 및 킬러 문항 1:1 완파',
slogan: '단순 공식 암기가 아닌 원리 이해와 킬러 문항 해결력을 기릅니다.',
details: [
{ title: '오답 4분류 역추적 클리닉', desc: '자주 실수하는 계산 오류 및 조건 누락 패턴을 1:1로 교정합니다.' },
{ title: '학교별 3개년 기출 족보 변형', desc: '인근 학교의 빈출 고난도 서술형 문항을 시험 전 3회 이상 체화합니다.' },
{ title: '50분 실전 타임어택 훈련', desc: '실제 시험 시간 부족을 해결하기 위해 문항별 시간 배분 루틴을 훈련합니다.' }
]
},
{
name: '영어과외',
subjectKey: 'english',
tag: '내신 필수',
image: '/img/영어과외.png',
desc: '교과서·부교재 전 지문 변형 및 서술형 영작',
slogan: '어휘, 문법, 서술형 감점 0점화로 내신 1등급을 완성합니다.',
details: [
{ title: '부교재 전 지문 어휘·문맥 변형', desc: '수능특강, 모의고사 기출 등 학교 부교재의 변형 출제 포인트를 완벽 대비합니다.' },
{ title: '서술형 조건 영작 1:1 첨삭', desc: '문법 조건 누락 감점을 원천 차단하는 정밀 첨삭 지도를 진행합니다.' },
{ title: '1:1 구문 독해 & 빈칸 추론 특훈', desc: '문장 구조 분석을 통해 킬러 빈칸·순서 배열 문제를 빠르고 정확히 풉니다.' }
]
},
// 2행: 국어, 과학
{
name: '국어과외',
subjectKey: 'korean',
tag: '문해력 완성',
image: '/img/국어과외.png',
desc: '비문학 독해 논리와 교과서 문학 1:1 정밀 분석',
slogan: '긴 지문도 흔들리지 않는 문해력과 서술형 채점 기준을 공략합니다.',
details: [
{ title: '비문학 구조 독해 공식 전수', desc: '제재별 핵심 키워드 연결과 선지 근거 찾기 훈련을 1:1로 코칭합니다.' },
{ title: '교과서 및 외부 지문 연계 분석', desc: '낯선 현대시·고전시가도 스스로 해석할 수 있는 감상 원리를 터득합니다.' },
{ title: '서술형 핵심 키워드 채점표 정복', desc: '출제자가 요구하는 조건에 맞춘 군더더기 없는 완벽한 답안 작성을 훈련합니다.' }
]
},
{
name: '과학과외',
subjectKey: 'science',
tag: '통합과학',
image: '/img/과학과외.png',
desc: '통합과학 원리 이해 및 물화생지 킬러 단원 정복',
slogan: '까다로운 계산과 복잡한 개념을 1:1 시각화와 원리 풀이로 해결합니다.',
details: [
{ title: '2026 개정 통합과학 개념 체계화', desc: '교과 단원 간 융합 개념을 알기 쉽게 정리하고 탐구형 문항을 대비합니다.' },
{ title: '물화생지 킬러 계산 단원 완파', desc: '역학, 화학 반응식, 유전 등 학생들이 가장 어려워하는 단원을 집중 지도합니다.' },
{ title: '수행평가 실험 보고서 1:1 가이드', desc: '지필고사뿐 아니라 감점되기 쉬운 과학 탐구 보고서 만점을 케어합니다.' }
]
},
// 3행: 사회 (1개 단독 센터 정렬)
{
name: '사회과외',
subjectKey: 'social',
tag: '통합사회',
image: '/img/사회과외.png',
desc: '통합사회·한국사 핵심 흐름 및 사탐 만점 전략',
slogan: '무작정 외우지 않고 역사와 사회 현상의 맥락을 이해하며 1등급을 쟁취합니다.',
details: [
{ title: '시대별 흐름 마인드맵 정리', desc: '단편적 암기가 아닌 전후 인과관계를 입체적으로 정리해 기억을 오래 유지합니다.' },
{ title: '자료 해석 및 그래프 변형 문항 정복', desc: '사탐 킬러로 출제되는 지도·통계·사료 분석 능력을 1:1로 키워줍니다.' },
{ title: '단기 서술형 족보 총정리', desc: '시험 3주 전 핵심 키워드와 단원별 요약 노트를 통해 내신 만점을 달성합니다.' }
]
}
]
const selectedItem = ref(null)
// 모달 오픈/클로즈
const openModal = (item) => {
selectedItem.value = item
if (typeof document !== 'undefined') {
document.body.style.overflow = 'hidden'
}
}
const closeModal = () => {
selectedItem.value = null
if (typeof document !== 'undefined') {
document.body.style.overflow = ''
}
}
// 모달 내 과목 선택 후 상담 신청 폼으로 이동
const applyWithSubject = (subjectName) => {
closeModal()
const cleanSubj = subjectName.replace(/과외$/, '')
const subjSelect = document.getElementById('weakSubject') || document.getElementById('c-subject')
if (subjSelect) {
subjSelect.value = cleanSubj
subjSelect.dispatchEvent(new Event('change'))
}
const formTarget = document.getElementById('leadFormSection') || document.getElementById('consult-section')
if (formTarget) {
formTarget.scrollIntoView({ behavior: 'smooth' })
}
}
// 해당 과목 전용 페이지로 이동
const goToSubjectPage = (subjectKey) => {
closeModal()
const dong = props.regionDong || '서울'
const grade = props.grade || '중학생'
const subMap = {
math: '수학',
english: '영어',
korean: '국어',
science: '과학',
social: '사회'
}
const subName = subMap[subjectKey] || '수학'
const targetUrl = `/${encodeURIComponent(dong)}-${encodeURIComponent(grade)}-${encodeURIComponent(subName)}`
router.push(targetUrl)
}
// ESC 키로 모달 닫기
const handleKeyDown = (e) => {
if (e.key === 'Escape' && selectedItem.value) {
closeModal()
}
}
onMounted(() => {
if (typeof window !== 'undefined') {
window.addEventListener('keydown', handleKeyDown)
}
})
onUnmounted(() => {
if (typeof window !== 'undefined') {
window.removeEventListener('keydown', handleKeyDown)
document.body.style.overflow = ''
}
})
</script>
<style scoped>
.subject-gallery-section {
width: 100%;
max-width: 1080px;
margin: 40px auto 60px;
padding: 0 16px;
position: relative;
box-sizing: border-box;
}
.gallery-container {
background: linear-gradient(180deg, #ffffff 0%, #f8fafc 100%);
border: 1px solid #e2e8f0;
border-radius: 28px;
padding: clamp(24px, 4vw, 44px) clamp(16px, 3vw, 36px);
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.05);
}
.gallery-header {
text-align: center;
margin-bottom: 32px;
}
.gallery-badge {
display: inline-flex;
align-items: center;
font-size: clamp(0.78rem, 2vw, 0.88rem);
font-weight: 700;
color: var(--primary-color, #1e3a8a);
background: rgba(30, 58, 138, 0.08);
padding: 6px 14px;
border-radius: 9999px;
margin-bottom: 10px;
}
.gallery-title {
font-size: clamp(1.35rem, 3.5vw, 1.95rem);
font-weight: 800;
color: #0f172a;
line-height: 1.35;
letter-spacing: -0.5px;
margin-bottom: 8px;
}
.gallery-title strong {
color: var(--primary-color, #1e3a8a);
}
.gallery-desc {
font-size: clamp(0.82rem, 2vw, 0.94rem);
color: #64748b;
word-break: keep-all;
}
/* 2 - 2 - 1 그리드 레이아웃 */
.subject-grid-221 {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
width: 100%;
}
/* 5번째 아이템: 3행 단독 1개 (2열 span 및 중앙 정렬) */
.card-item-5 {
grid-column: 1 / -1;
justify-self: center;
width: 100%;
max-width: calc(50% - 10px);
}
.gallery-card {
cursor: pointer;
border-radius: 20px;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
}
.card-inner {
background: #ffffff;
border-radius: 20px;
overflow: hidden;
border: 1px solid #e2e8f0;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.04);
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
display: flex;
flex-direction: column;
height: 100%;
}
.gallery-card:hover .card-inner {
transform: translateY(-6px);
box-shadow: 0 16px 32px rgba(30, 58, 138, 0.12);
border-color: #93c5fd;
}
.img-wrap {
position: relative;
width: 100%;
aspect-ratio: 1 / 1;
overflow: hidden;
background: #f1f5f9;
}
.subject-img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.5s ease;
}
.gallery-card:hover .subject-img {
transform: scale(1.05);
}
.subject-tag {
position: absolute;
top: 14px;
left: 14px;
background: rgba(15, 23, 42, 0.85);
backdrop-filter: blur(4px);
color: #ffffff;
font-size: 0.75rem;
font-weight: 800;
padding: 4px 12px;
border-radius: 9999px;
z-index: 2;
}
.zoom-overlay {
position: absolute;
inset: 0;
background: rgba(15, 23, 42, 0.4);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
z-index: 3;
}
.gallery-card:hover .zoom-overlay {
opacity: 1;
}
.zoom-btn {
background: #ffffff;
color: #0f172a;
font-size: 0.88rem;
font-weight: 800;
padding: 10px 18px;
border-radius: 9999px;
display: inline-flex;
align-items: center;
gap: 6px;
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
transform: translateY(6px);
transition: transform 0.3s ease;
}
.gallery-card:hover .zoom-btn {
transform: translateY(0);
}
.card-info {
padding: 18px 20px;
display: flex;
flex-direction: column;
flex: 1;
}
.card-subject-name {
display: flex;
align-items: baseline;
gap: 8px;
margin-bottom: 6px;
}
.sub-name {
font-size: 1.2rem;
font-weight: 800;
color: #0f172a;
}
.sub-grade {
font-size: 0.78rem;
font-weight: 700;
color: #64748b;
background: #f1f5f9;
padding: 2px 8px;
border-radius: 6px;
}
.card-subject-desc {
font-size: 0.85rem;
color: #475569;
line-height: 1.45;
margin-bottom: 14px;
flex: 1;
word-break: keep-all;
}
.card-action {
font-size: 0.82rem;
font-weight: 700;
color: var(--primary-color, #1e3a8a);
display: flex;
align-items: center;
gap: 6px;
transition: gap 0.2s ease;
}
.gallery-card:hover .card-action {
gap: 10px;
}
/* 모바일 반응형 대응 */
@media (max-width: 640px) {
.subject-grid-221 {
grid-template-columns: 1fr;
gap: 16px;
}
.card-item-5 {
grid-column: auto;
max-width: 100%;
justify-self: stretch;
}
}
/* 라이트박스 모달 */
.modal-backdrop {
position: fixed;
inset: 0;
background: rgba(15, 23, 42, 0.75);
backdrop-filter: blur(6px);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
padding: 16px;
}
.modal-card {
position: relative;
background: #ffffff;
border-radius: 24px;
max-width: 900px;
width: 100%;
max-height: 90vh;
overflow-y: auto;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
border: 1px solid rgba(255, 255, 255, 0.2);
}
.modal-close-btn {
position: absolute;
top: 16px;
right: 16px;
width: 36px;
height: 36px;
border-radius: 50%;
background: #f1f5f9;
border: none;
font-size: 1.1rem;
color: #475569;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
z-index: 20;
transition: all 0.2s ease;
}
.modal-close-btn:hover {
background: #e2e8f0;
color: #0f172a;
}
.modal-grid {
display: grid;
grid-template-columns: 1fr;
}
@media (min-width: 768px) {
.modal-grid {
grid-template-columns: 1fr 1.15fr;
}
}
.modal-img-col {
position: relative;
background: #0f172a;
display: flex;
align-items: center;
justify-content: center;
min-height: 300px;
}
.modal-main-img {
width: 100%;
height: 100%;
max-height: 520px;
object-fit: cover;
display: block;
}
.modal-img-badge {
position: absolute;
top: 16px;
left: 16px;
background: var(--accent-color, #d97706);
color: #ffffff;
font-size: 0.75rem;
font-weight: 800;
padding: 5px 12px;
border-radius: 9999px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
.modal-content-col {
padding: clamp(24px, 4vw, 36px);
display: flex;
flex-direction: column;
justify-content: space-between;
}
.modal-pill {
display: inline-block;
font-size: 0.75rem;
font-weight: 700;
color: var(--primary-color, #1e3a8a);
background: rgba(30, 58, 138, 0.08);
padding: 4px 10px;
border-radius: 9999px;
margin-bottom: 8px;
}
.modal-title {
font-size: clamp(1.4rem, 3vw, 1.85rem);
font-weight: 900;
color: #0f172a;
letter-spacing: -0.5px;
line-height: 1.25;
}
.modal-title .text-sub {
display: block;
font-size: 1rem;
font-weight: 700;
color: var(--primary-color, #1e3a8a);
margin-top: 4px;
}
.modal-slogan {
font-size: 0.88rem;
color: #475569;
margin-top: 8px;
line-height: 1.5;
word-break: keep-all;
}
.modal-points {
margin: 20px 0;
display: flex;
flex-direction: column;
gap: 12px;
background: #f8fafc;
padding: 16px;
border-radius: 16px;
border: 1px solid #e2e8f0;
}
.point-row {
display: flex;
gap: 12px;
align-items: flex-start;
}
.point-num {
font-size: 0.85rem;
font-weight: 900;
color: var(--primary-color, #1e3a8a);
background: #ffffff;
padding: 2px 8px;
border-radius: 6px;
border: 1px solid #cbd5e1;
flex-shrink: 0;
}
.point-head {
display: block;
font-size: 0.88rem;
font-weight: 800;
color: #1e293b;
margin-bottom: 2px;
}
.point-body {
font-size: 0.78rem;
color: #64748b;
line-height: 1.45;
word-break: keep-all;
}
.modal-actions {
display: flex;
gap: 10px;
flex-wrap: wrap;
margin-top: 10px;
}
.btn-modal-apply {
flex: 1 1 200px;
background: var(--primary-color, #1e3a8a);
color: #ffffff;
font-size: 0.92rem;
font-weight: 800;
padding: 14px 20px;
border-radius: 14px;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 14px rgba(30, 58, 138, 0.25);
transition: all 0.2s ease;
}
.btn-modal-apply:hover {
filter: brightness(1.1);
transform: translateY(-2px);
}
.btn-modal-link {
background: #f1f5f9;
color: #334155;
font-size: 0.85rem;
font-weight: 700;
padding: 14px 18px;
border-radius: 14px;
border: 1px solid #cbd5e1;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
}
.btn-modal-link:hover {
background: #e2e8f0;
color: #0f172a;
}
/* 모달 트랜지션 */
.modal-fade-enter-active,
.modal-fade-leave-active {
transition: opacity 0.3s ease;
}
.modal-fade-enter-from,
.modal-fade-leave-to {
opacity: 0;
}
.modal-fade-enter-active .modal-card,
.modal-fade-leave-active .modal-card {
transition: transform 0.3s cubic-bezier(0.25, 1, 0.5, 1);
}
.modal-fade-enter-from .modal-card,
.modal-fade-leave-to .modal-card {
transform: scale(0.92) translateY(20px);
}
</style>
+2 -16
View File
@@ -1,5 +1,5 @@
<template> <template>
<div class="landing-container bg-[#FAF5FF] text-slate-800 antialiased relative pb-24 md:pb-12 min-h-screen w-full"> <div class="landing-container bg-[#FAF5FF] text-slate-800 antialiased relative pb-8 min-h-screen w-full">
<!-- Header --> <!-- Header -->
<header class="bg-white border-b border-slate-200 sticky top-0 z-40 shadow-sm w-full"> <header class="bg-white border-b border-slate-200 sticky top-0 z-40 shadow-sm w-full">
@@ -352,20 +352,6 @@
</main> </main>
<!-- 하단 모바일 고정 CTA 바 -->
<aside class="fixed bottom-0 left-0 right-0 bg-white/95 backdrop-blur-md border-t border-slate-200 p-3 sm:p-4 z-40 shadow-2xl">
<div class="max-w-4xl mx-auto flex items-center gap-3">
<a href="tel:010-5961-5807" class="flex flex-col items-center justify-center px-4 py-2.5 bg-slate-100 hover:bg-slate-200 text-slate-800 rounded-xl text-xs font-bold shrink-0 transition" title="전화상담">
<i class="fa-solid fa-phone text-purple-700 text-sm mb-0.5"></i>
<span>010-5961-5807</span>
</a>
<a href="#leadFormSection" class="flex-1 bg-gradient-to-r from-purple-700 via-pink-600 to-purple-700 hover:opacity-95 text-white font-extrabold text-sm sm:text-base py-3 sm:py-3.5 px-4 rounded-xl shadow-lg transition flex items-center justify-center gap-2">
<i class="fa-solid fa-graduation-cap text-xs sm:text-sm"></i>
<span>지금 SKY 멘토링 무료 신청하기</span>
</a>
</div>
</aside>
</div> </div>
</template> </template>
-1
View File
@@ -96,7 +96,6 @@ export function getShortRegionName(sido: string, dong: string, sigungu?: string)
} }
// 경기, 인천, 광주, 부산, 대구, 대전 (예: 경기 수원 영통동, 대구 수성구 범어동) // 경기, 인천, 광주, 부산, 대구, 대전 (예: 경기 수원 영통동, 대구 수성구 범어동)
return `${prefix}${sigungu ? sigungu + ' ' : ''}${dong || ''}`.trim() return `${prefix}${sigungu ? sigungu + ' ' : ''}${dong || ''}`.trim()
} ${dong || ''}`.trim()
} }
// 지능형 URL 슬러그 파서 // 지능형 URL 슬러그 파서
+7 -3
View File
@@ -178,7 +178,7 @@ const handleSubmit = async () => {
try { try {
const currentUrl = typeof window !== 'undefined' ? window.location.href : '' const currentUrl = typeof window !== 'undefined' ? window.location.href : ''
await $fetch('/api/consult', { const res = await $fetch('/api/consult', {
method: 'POST', method: 'POST',
body: { body: {
studentName: form.value.studentName, studentName: form.value.studentName,
@@ -190,10 +190,14 @@ const handleSubmit = async () => {
url: currentUrl url: currentUrl
} }
}) })
if (res && res.success) {
submitted.value = true submitted.value = true
} else {
alert('상담 신청 접수 중 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.')
}
} catch (err) { } catch (err) {
console.error('상담 신청 전송:', err) console.error('상담 신청 전송 실패:', err)
submitted.value = true alert('상담 신청 접수 중 문제가 발생했습니다. 전화(010-5961-5807)로 문의해 주시기 바랍니다.')
} finally { } finally {
loading.value = false loading.value = false
} }
+783
View File
@@ -0,0 +1,783 @@
<template>
<section class="subject-gallery-section" aria-label="과목별 1:1 맞춤과외 갤러리">
<div class="gallery-container">
<!-- 섹션 헤더 -->
<div class="gallery-header">
<span class="gallery-badge">
<i class="fa-solid fa-sparkles mr-1"></i>
{{ regionDong ? `${regionDong} ` : '' }}과목별 1:1 전문 전담팀
</span>
<h2 class="gallery-title">
취약 과목을 1등급 전략 과목으로 역전시키는<br />
<strong>1:1 전담 과목별 클래스</strong>
</h2>
<p class="gallery-desc">
원하시는 과목 카드를 클릭하시면 1:1 맞춤 커리큘럼과 상세 안내를 페이지에서 크게 확인하실 수 있습니다.
</p>
</div>
<!-- 2 - 2 - 1 그리드 정렬 레이아웃 -->
<div class="subject-grid-221">
<div
v-for="(item, idx) in subjectList"
:key="item.name"
class="gallery-card"
:class="`card-item-${idx + 1}`"
@click="openModal(item)"
>
<div class="card-inner">
<div class="img-wrap">
<img
:src="item.image"
:alt="`${item.name} 1:1 맞춤 지도`"
class="subject-img"
loading="lazy"
/>
<span class="subject-tag">{{ item.tag }}</span>
<div class="zoom-overlay">
<span class="zoom-btn">
<i class="fa-solid fa-magnifying-glass-plus"></i>
<span>상세 보기</span>
</span>
</div>
</div>
<div class="card-info">
<div class="card-subject-name">
<span class="sub-name">{{ item.name }}</span>
<span class="sub-grade">{{ grade }}</span>
</div>
<p class="card-subject-desc">{{ item.desc }}</p>
<div class="card-action">
<span>자세히 보기 & 신청</span>
<i class="fa-solid fa-arrow-right"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 클릭 시 페이지에 크게 나오는 상세 모달 (Lightbox Modal) -->
<Teleport to="body">
<Transition name="modal-fade">
<div
v-if="selectedItem"
class="modal-backdrop"
@click.self="closeModal"
role="dialog"
aria-modal="true"
>
<div class="modal-card">
<!-- 닫기 버튼 -->
<button
type="button"
class="modal-close-btn"
@click="closeModal"
aria-label="닫기"
>
<i class="fa-solid fa-xmark"></i>
</button>
<div class="modal-grid">
<!-- 모달 좌측: 고해상도 생성 이미지 원본 -->
<div class="modal-img-col">
<img
:src="selectedItem.image"
:alt="`${selectedItem.name} 1:1 맞춤 과외`"
class="modal-main-img"
/>
<span class="modal-img-badge">{{ selectedItem.tag }}</span>
</div>
<!-- 모달 우측: 상세 설명 및 액션 버튼 -->
<div class="modal-content-col">
<div class="modal-header">
<span class="modal-pill">{{ regionDong || '관내' }} 1:1 밀착 코칭</span>
<h3 class="modal-title">
{{ selectedItem.name }}
<span class="text-sub">1:1 맞춤 마스터 클래스</span>
</h3>
<p class="modal-slogan">{{ selectedItem.slogan }}</p>
</div>
<div class="modal-points">
<div class="point-row" v-for="(pt, pIdx) in selectedItem.details" :key="pIdx">
<span class="point-num">0{{ pIdx + 1 }}</span>
<div>
<strong class="point-head">{{ pt.title }}</strong>
<p class="point-body">{{ pt.desc }}</p>
</div>
</div>
</div>
<!-- 모달 하단 액션 버튼 그룹 -->
<div class="modal-actions">
<button
type="button"
class="btn-modal-apply"
@click="applyWithSubject(selectedItem.name)"
>
<i class="fa-solid fa-paper-plane mr-2"></i>
<span>{{ selectedItem.name }} 무료 상담 신청하기</span>
</button>
<button
type="button"
class="btn-modal-link"
@click="goToSubjectPage(selectedItem.subjectKey)"
>
<span>전용 페이지 이동</span>
<i class="fa-solid fa-chevron-right ml-1"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</Transition>
</Teleport>
</section>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
const props = defineProps({
regionDong: {
type: String,
default: ''
},
grade: {
type: String,
default: '중·고등'
},
currentSubject: {
type: String,
default: ''
}
})
const router = useRouter()
// 5대 핵심 과목 (2 2 1 순서 배치)
const subjectList = [
// 1행: 수학, 영어
{
name: '수학과외',
subjectKey: 'math',
tag: '인기 1위',
image: '/img/수학과외.png',
desc: '개념 구멍 추적 및 킬러 문항 1:1 완파',
slogan: '단순 공식 암기가 아닌 원리 이해와 킬러 문항 해결력을 기릅니다.',
details: [
{ title: '오답 4분류 역추적 클리닉', desc: '자주 실수하는 계산 오류 및 조건 누락 패턴을 1:1로 교정합니다.' },
{ title: '학교별 3개년 기출 족보 변형', desc: '인근 학교의 빈출 고난도 서술형 문항을 시험 전 3회 이상 체화합니다.' },
{ title: '50분 실전 타임어택 훈련', desc: '실제 시험 시간 부족을 해결하기 위해 문항별 시간 배분 루틴을 훈련합니다.' }
]
},
{
name: '영어과외',
subjectKey: 'english',
tag: '내신 필수',
image: '/img/영어과외.png',
desc: '교과서·부교재 전 지문 변형 및 서술형 영작',
slogan: '어휘, 문법, 서술형 감점 0점화로 내신 1등급을 완성합니다.',
details: [
{ title: '부교재 전 지문 어휘·문맥 변형', desc: '수능특강, 모의고사 기출 등 학교 부교재의 변형 출제 포인트를 완벽 대비합니다.' },
{ title: '서술형 조건 영작 1:1 첨삭', desc: '문법 조건 누락 감점을 원천 차단하는 정밀 첨삭 지도를 진행합니다.' },
{ title: '1:1 구문 독해 & 빈칸 추론 특훈', desc: '문장 구조 분석을 통해 킬러 빈칸·순서 배열 문제를 빠르고 정확히 풉니다.' }
]
},
// 2행: 국어, 과학
{
name: '국어과외',
subjectKey: 'korean',
tag: '문해력 완성',
image: '/img/국어과외.png',
desc: '비문학 독해 논리와 교과서 문학 1:1 정밀 분석',
slogan: '긴 지문도 흔들리지 않는 문해력과 서술형 채점 기준을 공략합니다.',
details: [
{ title: '비문학 구조 독해 공식 전수', desc: '제재별 핵심 키워드 연결과 선지 근거 찾기 훈련을 1:1로 코칭합니다.' },
{ title: '교과서 및 외부 지문 연계 분석', desc: '낯선 현대시·고전시가도 스스로 해석할 수 있는 감상 원리를 터득합니다.' },
{ title: '서술형 핵심 키워드 채점표 정복', desc: '출제자가 요구하는 조건에 맞춘 군더더기 없는 완벽한 답안 작성을 훈련합니다.' }
]
},
{
name: '과학과외',
subjectKey: 'science',
tag: '통합과학',
image: '/img/과학과외.png',
desc: '통합과학 원리 이해 및 물화생지 킬러 단원 정복',
slogan: '까다로운 계산과 복잡한 개념을 1:1 시각화와 원리 풀이로 해결합니다.',
details: [
{ title: '2026 개정 통합과학 개념 체계화', desc: '교과 단원 간 융합 개념을 알기 쉽게 정리하고 탐구형 문항을 대비합니다.' },
{ title: '물화생지 킬러 계산 단원 완파', desc: '역학, 화학 반응식, 유전 등 학생들이 가장 어려워하는 단원을 집중 지도합니다.' },
{ title: '수행평가 실험 보고서 1:1 가이드', desc: '지필고사뿐 아니라 감점되기 쉬운 과학 탐구 보고서 만점을 케어합니다.' }
]
},
// 3행: 사회 (1개 단독 센터 정렬)
{
name: '사회과외',
subjectKey: 'social',
tag: '통합사회',
image: '/img/사회과외.png',
desc: '통합사회·한국사 핵심 흐름 및 사탐 만점 전략',
slogan: '무작정 외우지 않고 역사와 사회 현상의 맥락을 이해하며 1등급을 쟁취합니다.',
details: [
{ title: '시대별 흐름 마인드맵 정리', desc: '단편적 암기가 아닌 전후 인과관계를 입체적으로 정리해 기억을 오래 유지합니다.' },
{ title: '자료 해석 및 그래프 변형 문항 정복', desc: '사탐 킬러로 출제되는 지도·통계·사료 분석 능력을 1:1로 키워줍니다.' },
{ title: '단기 서술형 족보 총정리', desc: '시험 3주 전 핵심 키워드와 단원별 요약 노트를 통해 내신 만점을 달성합니다.' }
]
}
]
const selectedItem = ref(null)
// 모달 오픈/클로즈
const openModal = (item) => {
selectedItem.value = item
if (typeof document !== 'undefined') {
document.body.style.overflow = 'hidden'
}
}
const closeModal = () => {
selectedItem.value = null
if (typeof document !== 'undefined') {
document.body.style.overflow = ''
}
}
// 모달 내 과목 선택 후 상담 신청 폼으로 이동
const applyWithSubject = (subjectName) => {
closeModal()
const cleanSubj = subjectName.replace(/과외$/, '')
const subjSelect = document.getElementById('weakSubject') || document.getElementById('c-subject')
if (subjSelect) {
subjSelect.value = cleanSubj
subjSelect.dispatchEvent(new Event('change'))
}
const formTarget = document.getElementById('leadFormSection') || document.getElementById('consult-section')
if (formTarget) {
formTarget.scrollIntoView({ behavior: 'smooth' })
}
}
// 해당 과목 전용 페이지로 이동
const goToSubjectPage = (subjectKey) => {
closeModal()
const dong = props.regionDong || '서울'
const grade = props.grade || '중학생'
const subMap = {
math: '수학',
english: '영어',
korean: '국어',
science: '과학',
social: '사회'
}
const subName = subMap[subjectKey] || '수학'
const targetUrl = `/${encodeURIComponent(dong)}-${encodeURIComponent(grade)}-${encodeURIComponent(subName)}`
router.push(targetUrl)
}
// ESC 키로 모달 닫기
const handleKeyDown = (e) => {
if (e.key === 'Escape' && selectedItem.value) {
closeModal()
}
}
onMounted(() => {
if (typeof window !== 'undefined') {
window.addEventListener('keydown', handleKeyDown)
}
})
onUnmounted(() => {
if (typeof window !== 'undefined') {
window.removeEventListener('keydown', handleKeyDown)
document.body.style.overflow = ''
}
})
</script>
<style scoped>
.subject-gallery-section {
width: 100%;
max-width: 1080px;
margin: 40px auto 60px;
padding: 0 16px;
position: relative;
box-sizing: border-box;
}
.gallery-container {
background: linear-gradient(180deg, #ffffff 0%, #f8fafc 100%);
border: 1px solid #e2e8f0;
border-radius: 28px;
padding: clamp(24px, 4vw, 44px) clamp(16px, 3vw, 36px);
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.05);
}
.gallery-header {
text-align: center;
margin-bottom: 32px;
}
.gallery-badge {
display: inline-flex;
align-items: center;
font-size: clamp(0.78rem, 2vw, 0.88rem);
font-weight: 700;
color: var(--primary-color, #1e3a8a);
background: rgba(30, 58, 138, 0.08);
padding: 6px 14px;
border-radius: 9999px;
margin-bottom: 10px;
}
.gallery-title {
font-size: clamp(1.35rem, 3.5vw, 1.95rem);
font-weight: 800;
color: #0f172a;
line-height: 1.35;
letter-spacing: -0.5px;
margin-bottom: 8px;
}
.gallery-title strong {
color: var(--primary-color, #1e3a8a);
}
.gallery-desc {
font-size: clamp(0.82rem, 2vw, 0.94rem);
color: #64748b;
word-break: keep-all;
}
/* 2 - 2 - 1 그리드 레이아웃 */
.subject-grid-221 {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
width: 100%;
}
/* 5번째 아이템: 3행 단독 1개 (2열 span 및 중앙 정렬) */
.card-item-5 {
grid-column: 1 / -1;
justify-self: center;
width: 100%;
max-width: calc(50% - 10px);
}
.gallery-card {
cursor: pointer;
border-radius: 20px;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
}
.card-inner {
background: #ffffff;
border-radius: 20px;
overflow: hidden;
border: 1px solid #e2e8f0;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.04);
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
display: flex;
flex-direction: column;
height: 100%;
}
.gallery-card:hover .card-inner {
transform: translateY(-6px);
box-shadow: 0 16px 32px rgba(30, 58, 138, 0.12);
border-color: #93c5fd;
}
.img-wrap {
position: relative;
width: 100%;
aspect-ratio: 1 / 1;
overflow: hidden;
background: #f1f5f9;
}
.subject-img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.5s ease;
}
.gallery-card:hover .subject-img {
transform: scale(1.05);
}
.subject-tag {
position: absolute;
top: 14px;
left: 14px;
background: rgba(15, 23, 42, 0.85);
backdrop-filter: blur(4px);
color: #ffffff;
font-size: 0.75rem;
font-weight: 800;
padding: 4px 12px;
border-radius: 9999px;
z-index: 2;
}
.zoom-overlay {
position: absolute;
inset: 0;
background: rgba(15, 23, 42, 0.4);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
z-index: 3;
}
.gallery-card:hover .zoom-overlay {
opacity: 1;
}
.zoom-btn {
background: #ffffff;
color: #0f172a;
font-size: 0.88rem;
font-weight: 800;
padding: 10px 18px;
border-radius: 9999px;
display: inline-flex;
align-items: center;
gap: 6px;
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
transform: translateY(6px);
transition: transform 0.3s ease;
}
.gallery-card:hover .zoom-btn {
transform: translateY(0);
}
.card-info {
padding: 18px 20px;
display: flex;
flex-direction: column;
flex: 1;
}
.card-subject-name {
display: flex;
align-items: baseline;
gap: 8px;
margin-bottom: 6px;
}
.sub-name {
font-size: 1.2rem;
font-weight: 800;
color: #0f172a;
}
.sub-grade {
font-size: 0.78rem;
font-weight: 700;
color: #64748b;
background: #f1f5f9;
padding: 2px 8px;
border-radius: 6px;
}
.card-subject-desc {
font-size: 0.85rem;
color: #475569;
line-height: 1.45;
margin-bottom: 14px;
flex: 1;
word-break: keep-all;
}
.card-action {
font-size: 0.82rem;
font-weight: 700;
color: var(--primary-color, #1e3a8a);
display: flex;
align-items: center;
gap: 6px;
transition: gap 0.2s ease;
}
.gallery-card:hover .card-action {
gap: 10px;
}
/* 모바일 반응형 대응 */
@media (max-width: 640px) {
.subject-grid-221 {
grid-template-columns: 1fr;
gap: 16px;
}
.card-item-5 {
grid-column: auto;
max-width: 100%;
justify-self: stretch;
}
}
/* 라이트박스 모달 */
.modal-backdrop {
position: fixed;
inset: 0;
background: rgba(15, 23, 42, 0.75);
backdrop-filter: blur(6px);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
padding: 16px;
}
.modal-card {
position: relative;
background: #ffffff;
border-radius: 24px;
max-width: 900px;
width: 100%;
max-height: 90vh;
overflow-y: auto;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
border: 1px solid rgba(255, 255, 255, 0.2);
}
.modal-close-btn {
position: absolute;
top: 16px;
right: 16px;
width: 36px;
height: 36px;
border-radius: 50%;
background: #f1f5f9;
border: none;
font-size: 1.1rem;
color: #475569;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
z-index: 20;
transition: all 0.2s ease;
}
.modal-close-btn:hover {
background: #e2e8f0;
color: #0f172a;
}
.modal-grid {
display: grid;
grid-template-columns: 1fr;
}
@media (min-width: 768px) {
.modal-grid {
grid-template-columns: 1fr 1.15fr;
}
}
.modal-img-col {
position: relative;
background: #0f172a;
display: flex;
align-items: center;
justify-content: center;
min-height: 300px;
}
.modal-main-img {
width: 100%;
height: 100%;
max-height: 520px;
object-fit: cover;
display: block;
}
.modal-img-badge {
position: absolute;
top: 16px;
left: 16px;
background: var(--accent-color, #d97706);
color: #ffffff;
font-size: 0.75rem;
font-weight: 800;
padding: 5px 12px;
border-radius: 9999px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
.modal-content-col {
padding: clamp(24px, 4vw, 36px);
display: flex;
flex-direction: column;
justify-content: space-between;
}
.modal-pill {
display: inline-block;
font-size: 0.75rem;
font-weight: 700;
color: var(--primary-color, #1e3a8a);
background: rgba(30, 58, 138, 0.08);
padding: 4px 10px;
border-radius: 9999px;
margin-bottom: 8px;
}
.modal-title {
font-size: clamp(1.4rem, 3vw, 1.85rem);
font-weight: 900;
color: #0f172a;
letter-spacing: -0.5px;
line-height: 1.25;
}
.modal-title .text-sub {
display: block;
font-size: 1rem;
font-weight: 700;
color: var(--primary-color, #1e3a8a);
margin-top: 4px;
}
.modal-slogan {
font-size: 0.88rem;
color: #475569;
margin-top: 8px;
line-height: 1.5;
word-break: keep-all;
}
.modal-points {
margin: 20px 0;
display: flex;
flex-direction: column;
gap: 12px;
background: #f8fafc;
padding: 16px;
border-radius: 16px;
border: 1px solid #e2e8f0;
}
.point-row {
display: flex;
gap: 12px;
align-items: flex-start;
}
.point-num {
font-size: 0.85rem;
font-weight: 900;
color: var(--primary-color, #1e3a8a);
background: #ffffff;
padding: 2px 8px;
border-radius: 6px;
border: 1px solid #cbd5e1;
flex-shrink: 0;
}
.point-head {
display: block;
font-size: 0.88rem;
font-weight: 800;
color: #1e293b;
margin-bottom: 2px;
}
.point-body {
font-size: 0.78rem;
color: #64748b;
line-height: 1.45;
word-break: keep-all;
}
.modal-actions {
display: flex;
gap: 10px;
flex-wrap: wrap;
margin-top: 10px;
}
.btn-modal-apply {
flex: 1 1 200px;
background: var(--primary-color, #1e3a8a);
color: #ffffff;
font-size: 0.92rem;
font-weight: 800;
padding: 14px 20px;
border-radius: 14px;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 14px rgba(30, 58, 138, 0.25);
transition: all 0.2s ease;
}
.btn-modal-apply:hover {
filter: brightness(1.1);
transform: translateY(-2px);
}
.btn-modal-link {
background: #f1f5f9;
color: #334155;
font-size: 0.85rem;
font-weight: 700;
padding: 14px 18px;
border-radius: 14px;
border: 1px solid #cbd5e1;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
}
.btn-modal-link:hover {
background: #e2e8f0;
color: #0f172a;
}
/* 모달 트랜지션 */
.modal-fade-enter-active,
.modal-fade-leave-active {
transition: opacity 0.3s ease;
}
.modal-fade-enter-from,
.modal-fade-leave-to {
opacity: 0;
}
.modal-fade-enter-active .modal-card,
.modal-fade-leave-active .modal-card {
transition: transform 0.3s cubic-bezier(0.25, 1, 0.5, 1);
}
.modal-fade-enter-from .modal-card,
.modal-fade-leave-to .modal-card {
transform: scale(0.92) translateY(20px);
}
</style>
+2 -16
View File
@@ -1,5 +1,5 @@
<template> <template>
<div class="landing-container bg-[#FFF7ED] text-slate-800 antialiased relative pb-24 md:pb-12 min-h-screen w-full"> <div class="landing-container bg-[#FFF7ED] text-slate-800 antialiased relative pb-8 min-h-screen w-full">
<!-- Header --> <!-- Header -->
<header class="bg-white border-b border-slate-200 sticky top-0 z-40 shadow-sm w-full"> <header class="bg-white border-b border-slate-200 sticky top-0 z-40 shadow-sm w-full">
@@ -353,20 +353,6 @@
</main> </main>
<!-- 하단 모바일 고정 CTA 바 -->
<aside class="fixed bottom-0 left-0 right-0 bg-white/95 backdrop-blur-md border-t border-slate-200 p-3 sm:p-4 z-40 shadow-2xl">
<div class="max-w-4xl mx-auto flex items-center gap-3">
<a href="tel:010-5961-5807" class="flex flex-col items-center justify-center px-4 py-2.5 bg-slate-100 hover:bg-slate-200 text-slate-800 rounded-xl text-xs font-bold shrink-0 transition" title="전화상담">
<i class="fa-solid fa-phone text-orange-600 text-sm mb-0.5"></i>
<span>010-5961-5807</span>
</a>
<a href="#leadFormSection" class="flex-1 bg-gradient-to-r from-orange-600 via-amber-500 to-orange-600 hover:opacity-95 text-white font-extrabold text-sm sm:text-base py-3 sm:py-3.5 px-4 rounded-xl shadow-lg transition flex items-center justify-center gap-2">
<i class="fa-solid fa-heart-pulse text-xs sm:text-sm"></i>
<span>지금 무료 메타인지 코칭 신청하기</span>
</a>
</div>
</aside>
</div> </div>
</template> </template>
-1
View File
@@ -96,7 +96,6 @@ export function getShortRegionName(sido: string, dong: string, sigungu?: string)
} }
// 경기, 인천, 광주, 부산, 대구, 대전 (예: 경기 수원 영통동, 대구 수성구 범어동) // 경기, 인천, 광주, 부산, 대구, 대전 (예: 경기 수원 영통동, 대구 수성구 범어동)
return `${prefix}${sigungu ? sigungu + ' ' : ''}${dong || ''}`.trim() return `${prefix}${sigungu ? sigungu + ' ' : ''}${dong || ''}`.trim()
} ${dong || ''}`.trim()
} }
// 지능형 URL 슬러그 파서 // 지능형 URL 슬러그 파서
+7 -3
View File
@@ -178,7 +178,7 @@ const handleSubmit = async () => {
try { try {
const currentUrl = typeof window !== 'undefined' ? window.location.href : '' const currentUrl = typeof window !== 'undefined' ? window.location.href : ''
await $fetch('/api/consult', { const res = await $fetch('/api/consult', {
method: 'POST', method: 'POST',
body: { body: {
studentName: form.value.studentName, studentName: form.value.studentName,
@@ -190,10 +190,14 @@ const handleSubmit = async () => {
url: currentUrl url: currentUrl
} }
}) })
if (res && res.success) {
submitted.value = true submitted.value = true
} else {
alert('상담 신청 접수 중 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.')
}
} catch (err) { } catch (err) {
console.error('상담 신청 전송:', err) console.error('상담 신청 전송 실패:', err)
submitted.value = true alert('상담 신청 접수 중 문제가 발생했습니다. 전화(010-5961-5807)로 문의해 주시기 바랍니다.')
} finally { } finally {
loading.value = false loading.value = false
} }
+783
View File
@@ -0,0 +1,783 @@
<template>
<section class="subject-gallery-section" aria-label="과목별 1:1 맞춤과외 갤러리">
<div class="gallery-container">
<!-- 섹션 헤더 -->
<div class="gallery-header">
<span class="gallery-badge">
<i class="fa-solid fa-sparkles mr-1"></i>
{{ regionDong ? `${regionDong} ` : '' }}과목별 1:1 전문 전담팀
</span>
<h2 class="gallery-title">
취약 과목을 1등급 전략 과목으로 역전시키는<br />
<strong>1:1 전담 과목별 클래스</strong>
</h2>
<p class="gallery-desc">
원하시는 과목 카드를 클릭하시면 1:1 맞춤 커리큘럼과 상세 안내를 페이지에서 크게 확인하실 수 있습니다.
</p>
</div>
<!-- 2 - 2 - 1 그리드 정렬 레이아웃 -->
<div class="subject-grid-221">
<div
v-for="(item, idx) in subjectList"
:key="item.name"
class="gallery-card"
:class="`card-item-${idx + 1}`"
@click="openModal(item)"
>
<div class="card-inner">
<div class="img-wrap">
<img
:src="item.image"
:alt="`${item.name} 1:1 맞춤 지도`"
class="subject-img"
loading="lazy"
/>
<span class="subject-tag">{{ item.tag }}</span>
<div class="zoom-overlay">
<span class="zoom-btn">
<i class="fa-solid fa-magnifying-glass-plus"></i>
<span>상세 보기</span>
</span>
</div>
</div>
<div class="card-info">
<div class="card-subject-name">
<span class="sub-name">{{ item.name }}</span>
<span class="sub-grade">{{ grade }}</span>
</div>
<p class="card-subject-desc">{{ item.desc }}</p>
<div class="card-action">
<span>자세히 보기 & 신청</span>
<i class="fa-solid fa-arrow-right"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 클릭 시 페이지에 크게 나오는 상세 모달 (Lightbox Modal) -->
<Teleport to="body">
<Transition name="modal-fade">
<div
v-if="selectedItem"
class="modal-backdrop"
@click.self="closeModal"
role="dialog"
aria-modal="true"
>
<div class="modal-card">
<!-- 닫기 버튼 -->
<button
type="button"
class="modal-close-btn"
@click="closeModal"
aria-label="닫기"
>
<i class="fa-solid fa-xmark"></i>
</button>
<div class="modal-grid">
<!-- 모달 좌측: 고해상도 생성 이미지 원본 -->
<div class="modal-img-col">
<img
:src="selectedItem.image"
:alt="`${selectedItem.name} 1:1 맞춤 과외`"
class="modal-main-img"
/>
<span class="modal-img-badge">{{ selectedItem.tag }}</span>
</div>
<!-- 모달 우측: 상세 설명 및 액션 버튼 -->
<div class="modal-content-col">
<div class="modal-header">
<span class="modal-pill">{{ regionDong || '관내' }} 1:1 밀착 코칭</span>
<h3 class="modal-title">
{{ selectedItem.name }}
<span class="text-sub">1:1 맞춤 마스터 클래스</span>
</h3>
<p class="modal-slogan">{{ selectedItem.slogan }}</p>
</div>
<div class="modal-points">
<div class="point-row" v-for="(pt, pIdx) in selectedItem.details" :key="pIdx">
<span class="point-num">0{{ pIdx + 1 }}</span>
<div>
<strong class="point-head">{{ pt.title }}</strong>
<p class="point-body">{{ pt.desc }}</p>
</div>
</div>
</div>
<!-- 모달 하단 액션 버튼 그룹 -->
<div class="modal-actions">
<button
type="button"
class="btn-modal-apply"
@click="applyWithSubject(selectedItem.name)"
>
<i class="fa-solid fa-paper-plane mr-2"></i>
<span>{{ selectedItem.name }} 무료 상담 신청하기</span>
</button>
<button
type="button"
class="btn-modal-link"
@click="goToSubjectPage(selectedItem.subjectKey)"
>
<span>전용 페이지 이동</span>
<i class="fa-solid fa-chevron-right ml-1"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</Transition>
</Teleport>
</section>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
const props = defineProps({
regionDong: {
type: String,
default: ''
},
grade: {
type: String,
default: '중·고등'
},
currentSubject: {
type: String,
default: ''
}
})
const router = useRouter()
// 5대 핵심 과목 (2 2 1 순서 배치)
const subjectList = [
// 1행: 수학, 영어
{
name: '수학과외',
subjectKey: 'math',
tag: '인기 1위',
image: '/img/수학과외.png',
desc: '개념 구멍 추적 및 킬러 문항 1:1 완파',
slogan: '단순 공식 암기가 아닌 원리 이해와 킬러 문항 해결력을 기릅니다.',
details: [
{ title: '오답 4분류 역추적 클리닉', desc: '자주 실수하는 계산 오류 및 조건 누락 패턴을 1:1로 교정합니다.' },
{ title: '학교별 3개년 기출 족보 변형', desc: '인근 학교의 빈출 고난도 서술형 문항을 시험 전 3회 이상 체화합니다.' },
{ title: '50분 실전 타임어택 훈련', desc: '실제 시험 시간 부족을 해결하기 위해 문항별 시간 배분 루틴을 훈련합니다.' }
]
},
{
name: '영어과외',
subjectKey: 'english',
tag: '내신 필수',
image: '/img/영어과외.png',
desc: '교과서·부교재 전 지문 변형 및 서술형 영작',
slogan: '어휘, 문법, 서술형 감점 0점화로 내신 1등급을 완성합니다.',
details: [
{ title: '부교재 전 지문 어휘·문맥 변형', desc: '수능특강, 모의고사 기출 등 학교 부교재의 변형 출제 포인트를 완벽 대비합니다.' },
{ title: '서술형 조건 영작 1:1 첨삭', desc: '문법 조건 누락 감점을 원천 차단하는 정밀 첨삭 지도를 진행합니다.' },
{ title: '1:1 구문 독해 & 빈칸 추론 특훈', desc: '문장 구조 분석을 통해 킬러 빈칸·순서 배열 문제를 빠르고 정확히 풉니다.' }
]
},
// 2행: 국어, 과학
{
name: '국어과외',
subjectKey: 'korean',
tag: '문해력 완성',
image: '/img/국어과외.png',
desc: '비문학 독해 논리와 교과서 문학 1:1 정밀 분석',
slogan: '긴 지문도 흔들리지 않는 문해력과 서술형 채점 기준을 공략합니다.',
details: [
{ title: '비문학 구조 독해 공식 전수', desc: '제재별 핵심 키워드 연결과 선지 근거 찾기 훈련을 1:1로 코칭합니다.' },
{ title: '교과서 및 외부 지문 연계 분석', desc: '낯선 현대시·고전시가도 스스로 해석할 수 있는 감상 원리를 터득합니다.' },
{ title: '서술형 핵심 키워드 채점표 정복', desc: '출제자가 요구하는 조건에 맞춘 군더더기 없는 완벽한 답안 작성을 훈련합니다.' }
]
},
{
name: '과학과외',
subjectKey: 'science',
tag: '통합과학',
image: '/img/과학과외.png',
desc: '통합과학 원리 이해 및 물화생지 킬러 단원 정복',
slogan: '까다로운 계산과 복잡한 개념을 1:1 시각화와 원리 풀이로 해결합니다.',
details: [
{ title: '2026 개정 통합과학 개념 체계화', desc: '교과 단원 간 융합 개념을 알기 쉽게 정리하고 탐구형 문항을 대비합니다.' },
{ title: '물화생지 킬러 계산 단원 완파', desc: '역학, 화학 반응식, 유전 등 학생들이 가장 어려워하는 단원을 집중 지도합니다.' },
{ title: '수행평가 실험 보고서 1:1 가이드', desc: '지필고사뿐 아니라 감점되기 쉬운 과학 탐구 보고서 만점을 케어합니다.' }
]
},
// 3행: 사회 (1개 단독 센터 정렬)
{
name: '사회과외',
subjectKey: 'social',
tag: '통합사회',
image: '/img/사회과외.png',
desc: '통합사회·한국사 핵심 흐름 및 사탐 만점 전략',
slogan: '무작정 외우지 않고 역사와 사회 현상의 맥락을 이해하며 1등급을 쟁취합니다.',
details: [
{ title: '시대별 흐름 마인드맵 정리', desc: '단편적 암기가 아닌 전후 인과관계를 입체적으로 정리해 기억을 오래 유지합니다.' },
{ title: '자료 해석 및 그래프 변형 문항 정복', desc: '사탐 킬러로 출제되는 지도·통계·사료 분석 능력을 1:1로 키워줍니다.' },
{ title: '단기 서술형 족보 총정리', desc: '시험 3주 전 핵심 키워드와 단원별 요약 노트를 통해 내신 만점을 달성합니다.' }
]
}
]
const selectedItem = ref(null)
// 모달 오픈/클로즈
const openModal = (item) => {
selectedItem.value = item
if (typeof document !== 'undefined') {
document.body.style.overflow = 'hidden'
}
}
const closeModal = () => {
selectedItem.value = null
if (typeof document !== 'undefined') {
document.body.style.overflow = ''
}
}
// 모달 내 과목 선택 후 상담 신청 폼으로 이동
const applyWithSubject = (subjectName) => {
closeModal()
const cleanSubj = subjectName.replace(/과외$/, '')
const subjSelect = document.getElementById('weakSubject') || document.getElementById('c-subject')
if (subjSelect) {
subjSelect.value = cleanSubj
subjSelect.dispatchEvent(new Event('change'))
}
const formTarget = document.getElementById('leadFormSection') || document.getElementById('consult-section')
if (formTarget) {
formTarget.scrollIntoView({ behavior: 'smooth' })
}
}
// 해당 과목 전용 페이지로 이동
const goToSubjectPage = (subjectKey) => {
closeModal()
const dong = props.regionDong || '서울'
const grade = props.grade || '중학생'
const subMap = {
math: '수학',
english: '영어',
korean: '국어',
science: '과학',
social: '사회'
}
const subName = subMap[subjectKey] || '수학'
const targetUrl = `/${encodeURIComponent(dong)}-${encodeURIComponent(grade)}-${encodeURIComponent(subName)}`
router.push(targetUrl)
}
// ESC 키로 모달 닫기
const handleKeyDown = (e) => {
if (e.key === 'Escape' && selectedItem.value) {
closeModal()
}
}
onMounted(() => {
if (typeof window !== 'undefined') {
window.addEventListener('keydown', handleKeyDown)
}
})
onUnmounted(() => {
if (typeof window !== 'undefined') {
window.removeEventListener('keydown', handleKeyDown)
document.body.style.overflow = ''
}
})
</script>
<style scoped>
.subject-gallery-section {
width: 100%;
max-width: 1080px;
margin: 40px auto 60px;
padding: 0 16px;
position: relative;
box-sizing: border-box;
}
.gallery-container {
background: linear-gradient(180deg, #ffffff 0%, #f8fafc 100%);
border: 1px solid #e2e8f0;
border-radius: 28px;
padding: clamp(24px, 4vw, 44px) clamp(16px, 3vw, 36px);
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.05);
}
.gallery-header {
text-align: center;
margin-bottom: 32px;
}
.gallery-badge {
display: inline-flex;
align-items: center;
font-size: clamp(0.78rem, 2vw, 0.88rem);
font-weight: 700;
color: var(--primary-color, #1e3a8a);
background: rgba(30, 58, 138, 0.08);
padding: 6px 14px;
border-radius: 9999px;
margin-bottom: 10px;
}
.gallery-title {
font-size: clamp(1.35rem, 3.5vw, 1.95rem);
font-weight: 800;
color: #0f172a;
line-height: 1.35;
letter-spacing: -0.5px;
margin-bottom: 8px;
}
.gallery-title strong {
color: var(--primary-color, #1e3a8a);
}
.gallery-desc {
font-size: clamp(0.82rem, 2vw, 0.94rem);
color: #64748b;
word-break: keep-all;
}
/* 2 - 2 - 1 그리드 레이아웃 */
.subject-grid-221 {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
width: 100%;
}
/* 5번째 아이템: 3행 단독 1개 (2열 span 및 중앙 정렬) */
.card-item-5 {
grid-column: 1 / -1;
justify-self: center;
width: 100%;
max-width: calc(50% - 10px);
}
.gallery-card {
cursor: pointer;
border-radius: 20px;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
}
.card-inner {
background: #ffffff;
border-radius: 20px;
overflow: hidden;
border: 1px solid #e2e8f0;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.04);
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
display: flex;
flex-direction: column;
height: 100%;
}
.gallery-card:hover .card-inner {
transform: translateY(-6px);
box-shadow: 0 16px 32px rgba(30, 58, 138, 0.12);
border-color: #93c5fd;
}
.img-wrap {
position: relative;
width: 100%;
aspect-ratio: 1 / 1;
overflow: hidden;
background: #f1f5f9;
}
.subject-img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.5s ease;
}
.gallery-card:hover .subject-img {
transform: scale(1.05);
}
.subject-tag {
position: absolute;
top: 14px;
left: 14px;
background: rgba(15, 23, 42, 0.85);
backdrop-filter: blur(4px);
color: #ffffff;
font-size: 0.75rem;
font-weight: 800;
padding: 4px 12px;
border-radius: 9999px;
z-index: 2;
}
.zoom-overlay {
position: absolute;
inset: 0;
background: rgba(15, 23, 42, 0.4);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
z-index: 3;
}
.gallery-card:hover .zoom-overlay {
opacity: 1;
}
.zoom-btn {
background: #ffffff;
color: #0f172a;
font-size: 0.88rem;
font-weight: 800;
padding: 10px 18px;
border-radius: 9999px;
display: inline-flex;
align-items: center;
gap: 6px;
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
transform: translateY(6px);
transition: transform 0.3s ease;
}
.gallery-card:hover .zoom-btn {
transform: translateY(0);
}
.card-info {
padding: 18px 20px;
display: flex;
flex-direction: column;
flex: 1;
}
.card-subject-name {
display: flex;
align-items: baseline;
gap: 8px;
margin-bottom: 6px;
}
.sub-name {
font-size: 1.2rem;
font-weight: 800;
color: #0f172a;
}
.sub-grade {
font-size: 0.78rem;
font-weight: 700;
color: #64748b;
background: #f1f5f9;
padding: 2px 8px;
border-radius: 6px;
}
.card-subject-desc {
font-size: 0.85rem;
color: #475569;
line-height: 1.45;
margin-bottom: 14px;
flex: 1;
word-break: keep-all;
}
.card-action {
font-size: 0.82rem;
font-weight: 700;
color: var(--primary-color, #1e3a8a);
display: flex;
align-items: center;
gap: 6px;
transition: gap 0.2s ease;
}
.gallery-card:hover .card-action {
gap: 10px;
}
/* 모바일 반응형 대응 */
@media (max-width: 640px) {
.subject-grid-221 {
grid-template-columns: 1fr;
gap: 16px;
}
.card-item-5 {
grid-column: auto;
max-width: 100%;
justify-self: stretch;
}
}
/* 라이트박스 모달 */
.modal-backdrop {
position: fixed;
inset: 0;
background: rgba(15, 23, 42, 0.75);
backdrop-filter: blur(6px);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
padding: 16px;
}
.modal-card {
position: relative;
background: #ffffff;
border-radius: 24px;
max-width: 900px;
width: 100%;
max-height: 90vh;
overflow-y: auto;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
border: 1px solid rgba(255, 255, 255, 0.2);
}
.modal-close-btn {
position: absolute;
top: 16px;
right: 16px;
width: 36px;
height: 36px;
border-radius: 50%;
background: #f1f5f9;
border: none;
font-size: 1.1rem;
color: #475569;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
z-index: 20;
transition: all 0.2s ease;
}
.modal-close-btn:hover {
background: #e2e8f0;
color: #0f172a;
}
.modal-grid {
display: grid;
grid-template-columns: 1fr;
}
@media (min-width: 768px) {
.modal-grid {
grid-template-columns: 1fr 1.15fr;
}
}
.modal-img-col {
position: relative;
background: #0f172a;
display: flex;
align-items: center;
justify-content: center;
min-height: 300px;
}
.modal-main-img {
width: 100%;
height: 100%;
max-height: 520px;
object-fit: cover;
display: block;
}
.modal-img-badge {
position: absolute;
top: 16px;
left: 16px;
background: var(--accent-color, #d97706);
color: #ffffff;
font-size: 0.75rem;
font-weight: 800;
padding: 5px 12px;
border-radius: 9999px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
.modal-content-col {
padding: clamp(24px, 4vw, 36px);
display: flex;
flex-direction: column;
justify-content: space-between;
}
.modal-pill {
display: inline-block;
font-size: 0.75rem;
font-weight: 700;
color: var(--primary-color, #1e3a8a);
background: rgba(30, 58, 138, 0.08);
padding: 4px 10px;
border-radius: 9999px;
margin-bottom: 8px;
}
.modal-title {
font-size: clamp(1.4rem, 3vw, 1.85rem);
font-weight: 900;
color: #0f172a;
letter-spacing: -0.5px;
line-height: 1.25;
}
.modal-title .text-sub {
display: block;
font-size: 1rem;
font-weight: 700;
color: var(--primary-color, #1e3a8a);
margin-top: 4px;
}
.modal-slogan {
font-size: 0.88rem;
color: #475569;
margin-top: 8px;
line-height: 1.5;
word-break: keep-all;
}
.modal-points {
margin: 20px 0;
display: flex;
flex-direction: column;
gap: 12px;
background: #f8fafc;
padding: 16px;
border-radius: 16px;
border: 1px solid #e2e8f0;
}
.point-row {
display: flex;
gap: 12px;
align-items: flex-start;
}
.point-num {
font-size: 0.85rem;
font-weight: 900;
color: var(--primary-color, #1e3a8a);
background: #ffffff;
padding: 2px 8px;
border-radius: 6px;
border: 1px solid #cbd5e1;
flex-shrink: 0;
}
.point-head {
display: block;
font-size: 0.88rem;
font-weight: 800;
color: #1e293b;
margin-bottom: 2px;
}
.point-body {
font-size: 0.78rem;
color: #64748b;
line-height: 1.45;
word-break: keep-all;
}
.modal-actions {
display: flex;
gap: 10px;
flex-wrap: wrap;
margin-top: 10px;
}
.btn-modal-apply {
flex: 1 1 200px;
background: var(--primary-color, #1e3a8a);
color: #ffffff;
font-size: 0.92rem;
font-weight: 800;
padding: 14px 20px;
border-radius: 14px;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 14px rgba(30, 58, 138, 0.25);
transition: all 0.2s ease;
}
.btn-modal-apply:hover {
filter: brightness(1.1);
transform: translateY(-2px);
}
.btn-modal-link {
background: #f1f5f9;
color: #334155;
font-size: 0.85rem;
font-weight: 700;
padding: 14px 18px;
border-radius: 14px;
border: 1px solid #cbd5e1;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
}
.btn-modal-link:hover {
background: #e2e8f0;
color: #0f172a;
}
/* 모달 트랜지션 */
.modal-fade-enter-active,
.modal-fade-leave-active {
transition: opacity 0.3s ease;
}
.modal-fade-enter-from,
.modal-fade-leave-to {
opacity: 0;
}
.modal-fade-enter-active .modal-card,
.modal-fade-leave-active .modal-card {
transition: transform 0.3s cubic-bezier(0.25, 1, 0.5, 1);
}
.modal-fade-enter-from .modal-card,
.modal-fade-leave-to .modal-card {
transform: scale(0.92) translateY(20px);
}
</style>
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

+7
View File
@@ -62,6 +62,13 @@
:subjectName="parsed.subjectName" :subjectName="parsed.subjectName"
/> />
<!-- 12. 과목별 1타 강사진 갤러리 캐러셀 (클릭 시 페이지 모달 확대 및 상담 연동) -->
<SubjectCarousel
:regionDong="parsed.dong"
:grade="parsed.grade"
:currentSubject="parsed.subjectName"
/>
<!-- 웹 광고 단일 목적: 해당 학년과 과목이 기본 선택된 무료 상담 신청 폼 --> <!-- 웹 광고 단일 목적: 해당 학년과 과목이 기본 선택된 무료 상담 신청 폼 -->
<ConsultForm <ConsultForm
:regionName="parsed.shortRegionName" :regionName="parsed.shortRegionName"
+5 -16
View File
@@ -1,5 +1,5 @@
<template> <template>
<div class="landing-container bg-[#F8FAFC] text-slate-800 antialiased relative pb-24 md:pb-12 min-h-screen w-full"> <div class="landing-container bg-[#F8FAFC] text-slate-800 antialiased relative pb-8 min-h-screen w-full">
<!-- Header --> <!-- Header -->
<header class="bg-white border-b border-slate-200 sticky top-0 z-40 shadow-sm w-full"> <header class="bg-white border-b border-slate-200 sticky top-0 z-40 shadow-sm w-full">
@@ -330,6 +330,9 @@
</div> </div>
</section> </section>
<!-- 과목별 1:1 맞춤과외 갤러리 캐러셀 (클릭 시 확대 모달 및 상담/이동) -->
<SubjectCarousel grade="초·중·고" />
<!-- FAQ 섹션 --> <!-- FAQ 섹션 -->
<section class="mt-16 px-4 sm:px-6 max-w-4xl mx-auto"> <section class="mt-16 px-4 sm:px-6 max-w-4xl mx-auto">
<header class="text-center mb-8"> <header class="text-center mb-8">
@@ -353,20 +356,6 @@
</main> </main>
<!-- 하단 모바일 고정 CTA 바 -->
<aside class="fixed bottom-0 left-0 right-0 bg-white/95 backdrop-blur-md border-t border-slate-200 p-3 sm:p-4 z-40 shadow-2xl">
<div class="max-w-4xl mx-auto flex items-center gap-3">
<a href="tel:010-5961-5807" class="flex flex-col items-center justify-center px-4 py-2.5 bg-slate-100 hover:bg-slate-200 text-slate-800 rounded-xl text-xs font-bold shrink-0 transition" title="전화상담">
<i class="fa-solid fa-phone text-indigo-700 text-sm mb-0.5"></i>
<span>010-5961-5807</span>
</a>
<a href="#leadFormSection" class="flex-1 bg-gradient-to-r from-orange-600 via-amber-500 to-orange-600 hover:opacity-95 text-white font-extrabold text-sm sm:text-base py-3 sm:py-3.5 px-4 rounded-xl shadow-lg transition flex items-center justify-center gap-2">
<i class="fa-solid fa-file-lines text-xs sm:text-sm"></i>
<span>지금 내신 족보 & 1:1 상담 신청하기</span>
</a>
</div>
</aside>
</div> </div>
</template> </template>
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

-1
View File
@@ -96,7 +96,6 @@ export function getShortRegionName(sido: string, dong: string, sigungu?: string)
} }
// 경기, 인천, 광주, 부산, 대구, 대전 (예: 경기 수원 영통동, 대구 수성구 범어동) // 경기, 인천, 광주, 부산, 대구, 대전 (예: 경기 수원 영통동, 대구 수성구 범어동)
return `${prefix}${sigungu ? sigungu + ' ' : ''}${dong || ''}`.trim() return `${prefix}${sigungu ? sigungu + ' ' : ''}${dong || ''}`.trim()
} ${dong || ''}`.trim()
} }
// 지능형 URL 슬러그 파서 // 지능형 URL 슬러그 파서
+7 -3
View File
@@ -178,7 +178,7 @@ const handleSubmit = async () => {
try { try {
const currentUrl = typeof window !== 'undefined' ? window.location.href : '' const currentUrl = typeof window !== 'undefined' ? window.location.href : ''
await $fetch('/api/consult', { const res = await $fetch('/api/consult', {
method: 'POST', method: 'POST',
body: { body: {
studentName: form.value.studentName, studentName: form.value.studentName,
@@ -190,10 +190,14 @@ const handleSubmit = async () => {
url: currentUrl url: currentUrl
} }
}) })
if (res && res.success) {
submitted.value = true submitted.value = true
} else {
alert('상담 신청 접수 중 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.')
}
} catch (err) { } catch (err) {
console.error('상담 신청 전송:', err) console.error('상담 신청 전송 실패:', err)
submitted.value = true alert('상담 신청 접수 중 문제가 발생했습니다. 전화(010-5961-5807)로 문의해 주시기 바랍니다.')
} finally { } finally {
loading.value = false loading.value = false
} }
+19 -5
View File
@@ -116,6 +116,7 @@
<script setup> <script setup>
import { computed } from 'vue' import { computed } from 'vue'
import schoolsIndex from '../data/schools_index.json' import schoolsIndex from '../data/schools_index.json'
import { getRegionByDong } from '../utils/dataHelper'
const props = defineProps({ const props = defineProps({
regionDong: { regionDong: {
@@ -141,7 +142,7 @@ const targetSchoolType = computed(() => {
return '초·중학교' return '초·중학교'
}) })
// 동네 기준 또는 구 기준 인근 고등학교 목록 // 동네 기준 또는 관할 시군구 기준 인근 고등학교 목록
const nearbyHighSchools = computed(() => { const nearbyHighSchools = computed(() => {
const dong = props.regionDong || '' const dong = props.regionDong || ''
const cleanDong = dong.trim() const cleanDong = dong.trim()
@@ -158,10 +159,23 @@ const nearbyHighSchools = computed(() => {
} }
} }
// 3. 동네에 고등학교가 없으면 관할 구/시 또는 인접 구의 학교 상위 6개 // 3. 동네에 고등학교가 없으면 동일 관할 시군구 학교 상위 6개 검색
for (const [gu, list] of Object.entries(schoolsIndex.bySigungu || {})) { const regInfo = getRegionByDong(cleanDong)
if (cleanDong.includes(gu) || gu.includes(cleanDong)) { if (regInfo && regInfo.sigungu) {
return list.slice(0, 6) const targetSigungu = regInfo.sigungu.trim()
const matchedBySigungu = []
for (const list of Object.values(schoolsIndex.byDong || {})) {
for (const sch of list) {
if (sch.sigungu && (sch.sigungu.includes(targetSigungu) || targetSigungu.includes(sch.sigungu))) {
if (!matchedBySigungu.some(m => m.code === sch.code)) {
matchedBySigungu.push(sch)
}
}
}
if (matchedBySigungu.length >= 6) break
}
if (matchedBySigungu.length > 0) {
return matchedBySigungu.slice(0, 6)
} }
} }
+783
View File
@@ -0,0 +1,783 @@
<template>
<section class="subject-gallery-section" aria-label="과목별 1:1 맞춤과외 갤러리">
<div class="gallery-container">
<!-- 섹션 헤더 -->
<div class="gallery-header">
<span class="gallery-badge">
<i class="fa-solid fa-sparkles mr-1"></i>
{{ regionDong ? `${regionDong} ` : '' }}과목별 1:1 전문 전담팀
</span>
<h2 class="gallery-title">
취약 과목을 1등급 전략 과목으로 역전시키는<br />
<strong>1:1 전담 과목별 클래스</strong>
</h2>
<p class="gallery-desc">
원하시는 과목 카드를 클릭하시면 1:1 맞춤 커리큘럼과 상세 안내를 페이지에서 크게 확인하실 수 있습니다.
</p>
</div>
<!-- 2 - 2 - 1 그리드 정렬 레이아웃 -->
<div class="subject-grid-221">
<div
v-for="(item, idx) in subjectList"
:key="item.name"
class="gallery-card"
:class="`card-item-${idx + 1}`"
@click="openModal(item)"
>
<div class="card-inner">
<div class="img-wrap">
<img
:src="item.image"
:alt="`${item.name} 1:1 맞춤 지도`"
class="subject-img"
loading="lazy"
/>
<span class="subject-tag">{{ item.tag }}</span>
<div class="zoom-overlay">
<span class="zoom-btn">
<i class="fa-solid fa-magnifying-glass-plus"></i>
<span>상세 보기</span>
</span>
</div>
</div>
<div class="card-info">
<div class="card-subject-name">
<span class="sub-name">{{ item.name }}</span>
<span class="sub-grade">{{ grade }}</span>
</div>
<p class="card-subject-desc">{{ item.desc }}</p>
<div class="card-action">
<span>자세히 보기 & 신청</span>
<i class="fa-solid fa-arrow-right"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 클릭 시 페이지에 크게 나오는 상세 모달 (Lightbox Modal) -->
<Teleport to="body">
<Transition name="modal-fade">
<div
v-if="selectedItem"
class="modal-backdrop"
@click.self="closeModal"
role="dialog"
aria-modal="true"
>
<div class="modal-card">
<!-- 닫기 버튼 -->
<button
type="button"
class="modal-close-btn"
@click="closeModal"
aria-label="닫기"
>
<i class="fa-solid fa-xmark"></i>
</button>
<div class="modal-grid">
<!-- 모달 좌측: 고해상도 생성 이미지 원본 -->
<div class="modal-img-col">
<img
:src="selectedItem.image"
:alt="`${selectedItem.name} 1:1 맞춤 과외`"
class="modal-main-img"
/>
<span class="modal-img-badge">{{ selectedItem.tag }}</span>
</div>
<!-- 모달 우측: 상세 설명 및 액션 버튼 -->
<div class="modal-content-col">
<div class="modal-header">
<span class="modal-pill">{{ regionDong || '관내' }} 1:1 밀착 코칭</span>
<h3 class="modal-title">
{{ selectedItem.name }}
<span class="text-sub">1:1 맞춤 마스터 클래스</span>
</h3>
<p class="modal-slogan">{{ selectedItem.slogan }}</p>
</div>
<div class="modal-points">
<div class="point-row" v-for="(pt, pIdx) in selectedItem.details" :key="pIdx">
<span class="point-num">0{{ pIdx + 1 }}</span>
<div>
<strong class="point-head">{{ pt.title }}</strong>
<p class="point-body">{{ pt.desc }}</p>
</div>
</div>
</div>
<!-- 모달 하단 액션 버튼 그룹 -->
<div class="modal-actions">
<button
type="button"
class="btn-modal-apply"
@click="applyWithSubject(selectedItem.name)"
>
<i class="fa-solid fa-paper-plane mr-2"></i>
<span>{{ selectedItem.name }} 무료 상담 신청하기</span>
</button>
<button
type="button"
class="btn-modal-link"
@click="goToSubjectPage(selectedItem.subjectKey)"
>
<span>전용 페이지 이동</span>
<i class="fa-solid fa-chevron-right ml-1"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</Transition>
</Teleport>
</section>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
const props = defineProps({
regionDong: {
type: String,
default: ''
},
grade: {
type: String,
default: '중·고등'
},
currentSubject: {
type: String,
default: ''
}
})
const router = useRouter()
// 5대 핵심 과목 (2 2 1 순서 배치)
const subjectList = [
// 1행: 수학, 영어
{
name: '수학과외',
subjectKey: 'math',
tag: '인기 1위',
image: '/img/수학과외.png',
desc: '개념 구멍 추적 및 킬러 문항 1:1 완파',
slogan: '단순 공식 암기가 아닌 원리 이해와 킬러 문항 해결력을 기릅니다.',
details: [
{ title: '오답 4분류 역추적 클리닉', desc: '자주 실수하는 계산 오류 및 조건 누락 패턴을 1:1로 교정합니다.' },
{ title: '학교별 3개년 기출 족보 변형', desc: '인근 학교의 빈출 고난도 서술형 문항을 시험 전 3회 이상 체화합니다.' },
{ title: '50분 실전 타임어택 훈련', desc: '실제 시험 시간 부족을 해결하기 위해 문항별 시간 배분 루틴을 훈련합니다.' }
]
},
{
name: '영어과외',
subjectKey: 'english',
tag: '내신 필수',
image: '/img/영어과외.png',
desc: '교과서·부교재 전 지문 변형 및 서술형 영작',
slogan: '어휘, 문법, 서술형 감점 0점화로 내신 1등급을 완성합니다.',
details: [
{ title: '부교재 전 지문 어휘·문맥 변형', desc: '수능특강, 모의고사 기출 등 학교 부교재의 변형 출제 포인트를 완벽 대비합니다.' },
{ title: '서술형 조건 영작 1:1 첨삭', desc: '문법 조건 누락 감점을 원천 차단하는 정밀 첨삭 지도를 진행합니다.' },
{ title: '1:1 구문 독해 & 빈칸 추론 특훈', desc: '문장 구조 분석을 통해 킬러 빈칸·순서 배열 문제를 빠르고 정확히 풉니다.' }
]
},
// 2행: 국어, 과학
{
name: '국어과외',
subjectKey: 'korean',
tag: '문해력 완성',
image: '/img/국어과외.png',
desc: '비문학 독해 논리와 교과서 문학 1:1 정밀 분석',
slogan: '긴 지문도 흔들리지 않는 문해력과 서술형 채점 기준을 공략합니다.',
details: [
{ title: '비문학 구조 독해 공식 전수', desc: '제재별 핵심 키워드 연결과 선지 근거 찾기 훈련을 1:1로 코칭합니다.' },
{ title: '교과서 및 외부 지문 연계 분석', desc: '낯선 현대시·고전시가도 스스로 해석할 수 있는 감상 원리를 터득합니다.' },
{ title: '서술형 핵심 키워드 채점표 정복', desc: '출제자가 요구하는 조건에 맞춘 군더더기 없는 완벽한 답안 작성을 훈련합니다.' }
]
},
{
name: '과학과외',
subjectKey: 'science',
tag: '통합과학',
image: '/img/과학과외.png',
desc: '통합과학 원리 이해 및 물화생지 킬러 단원 정복',
slogan: '까다로운 계산과 복잡한 개념을 1:1 시각화와 원리 풀이로 해결합니다.',
details: [
{ title: '2026 개정 통합과학 개념 체계화', desc: '교과 단원 간 융합 개념을 알기 쉽게 정리하고 탐구형 문항을 대비합니다.' },
{ title: '물화생지 킬러 계산 단원 완파', desc: '역학, 화학 반응식, 유전 등 학생들이 가장 어려워하는 단원을 집중 지도합니다.' },
{ title: '수행평가 실험 보고서 1:1 가이드', desc: '지필고사뿐 아니라 감점되기 쉬운 과학 탐구 보고서 만점을 케어합니다.' }
]
},
// 3행: 사회 (1개 단독 센터 정렬)
{
name: '사회과외',
subjectKey: 'social',
tag: '통합사회',
image: '/img/사회과외.png',
desc: '통합사회·한국사 핵심 흐름 및 사탐 만점 전략',
slogan: '무작정 외우지 않고 역사와 사회 현상의 맥락을 이해하며 1등급을 쟁취합니다.',
details: [
{ title: '시대별 흐름 마인드맵 정리', desc: '단편적 암기가 아닌 전후 인과관계를 입체적으로 정리해 기억을 오래 유지합니다.' },
{ title: '자료 해석 및 그래프 변형 문항 정복', desc: '사탐 킬러로 출제되는 지도·통계·사료 분석 능력을 1:1로 키워줍니다.' },
{ title: '단기 서술형 족보 총정리', desc: '시험 3주 전 핵심 키워드와 단원별 요약 노트를 통해 내신 만점을 달성합니다.' }
]
}
]
const selectedItem = ref(null)
// 모달 오픈/클로즈
const openModal = (item) => {
selectedItem.value = item
if (typeof document !== 'undefined') {
document.body.style.overflow = 'hidden'
}
}
const closeModal = () => {
selectedItem.value = null
if (typeof document !== 'undefined') {
document.body.style.overflow = ''
}
}
// 모달 내 과목 선택 후 상담 신청 폼으로 이동
const applyWithSubject = (subjectName) => {
closeModal()
const cleanSubj = subjectName.replace(/과외$/, '')
const subjSelect = document.getElementById('weakSubject') || document.getElementById('c-subject')
if (subjSelect) {
subjSelect.value = cleanSubj
subjSelect.dispatchEvent(new Event('change'))
}
const formTarget = document.getElementById('leadFormSection') || document.getElementById('consult-section')
if (formTarget) {
formTarget.scrollIntoView({ behavior: 'smooth' })
}
}
// 해당 과목 전용 페이지로 이동
const goToSubjectPage = (subjectKey) => {
closeModal()
const dong = props.regionDong || '서울'
const grade = props.grade || '중학생'
const subMap = {
math: '수학',
english: '영어',
korean: '국어',
science: '과학',
social: '사회'
}
const subName = subMap[subjectKey] || '수학'
const targetUrl = `/${encodeURIComponent(dong)}-${encodeURIComponent(grade)}-${encodeURIComponent(subName)}`
router.push(targetUrl)
}
// ESC 키로 모달 닫기
const handleKeyDown = (e) => {
if (e.key === 'Escape' && selectedItem.value) {
closeModal()
}
}
onMounted(() => {
if (typeof window !== 'undefined') {
window.addEventListener('keydown', handleKeyDown)
}
})
onUnmounted(() => {
if (typeof window !== 'undefined') {
window.removeEventListener('keydown', handleKeyDown)
document.body.style.overflow = ''
}
})
</script>
<style scoped>
.subject-gallery-section {
width: 100%;
max-width: 1080px;
margin: 40px auto 60px;
padding: 0 16px;
position: relative;
box-sizing: border-box;
}
.gallery-container {
background: linear-gradient(180deg, #ffffff 0%, #f8fafc 100%);
border: 1px solid #e2e8f0;
border-radius: 28px;
padding: clamp(24px, 4vw, 44px) clamp(16px, 3vw, 36px);
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.05);
}
.gallery-header {
text-align: center;
margin-bottom: 32px;
}
.gallery-badge {
display: inline-flex;
align-items: center;
font-size: clamp(0.78rem, 2vw, 0.88rem);
font-weight: 700;
color: var(--primary-color, #1e3a8a);
background: rgba(30, 58, 138, 0.08);
padding: 6px 14px;
border-radius: 9999px;
margin-bottom: 10px;
}
.gallery-title {
font-size: clamp(1.35rem, 3.5vw, 1.95rem);
font-weight: 800;
color: #0f172a;
line-height: 1.35;
letter-spacing: -0.5px;
margin-bottom: 8px;
}
.gallery-title strong {
color: var(--primary-color, #1e3a8a);
}
.gallery-desc {
font-size: clamp(0.82rem, 2vw, 0.94rem);
color: #64748b;
word-break: keep-all;
}
/* 2 - 2 - 1 그리드 레이아웃 */
.subject-grid-221 {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
width: 100%;
}
/* 5번째 아이템: 3행 단독 1개 (2열 span 및 중앙 정렬) */
.card-item-5 {
grid-column: 1 / -1;
justify-self: center;
width: 100%;
max-width: calc(50% - 10px);
}
.gallery-card {
cursor: pointer;
border-radius: 20px;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
}
.card-inner {
background: #ffffff;
border-radius: 20px;
overflow: hidden;
border: 1px solid #e2e8f0;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.04);
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
display: flex;
flex-direction: column;
height: 100%;
}
.gallery-card:hover .card-inner {
transform: translateY(-6px);
box-shadow: 0 16px 32px rgba(30, 58, 138, 0.12);
border-color: #93c5fd;
}
.img-wrap {
position: relative;
width: 100%;
aspect-ratio: 1 / 1;
overflow: hidden;
background: #f1f5f9;
}
.subject-img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.5s ease;
}
.gallery-card:hover .subject-img {
transform: scale(1.05);
}
.subject-tag {
position: absolute;
top: 14px;
left: 14px;
background: rgba(15, 23, 42, 0.85);
backdrop-filter: blur(4px);
color: #ffffff;
font-size: 0.75rem;
font-weight: 800;
padding: 4px 12px;
border-radius: 9999px;
z-index: 2;
}
.zoom-overlay {
position: absolute;
inset: 0;
background: rgba(15, 23, 42, 0.4);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
z-index: 3;
}
.gallery-card:hover .zoom-overlay {
opacity: 1;
}
.zoom-btn {
background: #ffffff;
color: #0f172a;
font-size: 0.88rem;
font-weight: 800;
padding: 10px 18px;
border-radius: 9999px;
display: inline-flex;
align-items: center;
gap: 6px;
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
transform: translateY(6px);
transition: transform 0.3s ease;
}
.gallery-card:hover .zoom-btn {
transform: translateY(0);
}
.card-info {
padding: 18px 20px;
display: flex;
flex-direction: column;
flex: 1;
}
.card-subject-name {
display: flex;
align-items: baseline;
gap: 8px;
margin-bottom: 6px;
}
.sub-name {
font-size: 1.2rem;
font-weight: 800;
color: #0f172a;
}
.sub-grade {
font-size: 0.78rem;
font-weight: 700;
color: #64748b;
background: #f1f5f9;
padding: 2px 8px;
border-radius: 6px;
}
.card-subject-desc {
font-size: 0.85rem;
color: #475569;
line-height: 1.45;
margin-bottom: 14px;
flex: 1;
word-break: keep-all;
}
.card-action {
font-size: 0.82rem;
font-weight: 700;
color: var(--primary-color, #1e3a8a);
display: flex;
align-items: center;
gap: 6px;
transition: gap 0.2s ease;
}
.gallery-card:hover .card-action {
gap: 10px;
}
/* 모바일 반응형 대응 */
@media (max-width: 640px) {
.subject-grid-221 {
grid-template-columns: 1fr;
gap: 16px;
}
.card-item-5 {
grid-column: auto;
max-width: 100%;
justify-self: stretch;
}
}
/* 라이트박스 모달 */
.modal-backdrop {
position: fixed;
inset: 0;
background: rgba(15, 23, 42, 0.75);
backdrop-filter: blur(6px);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
padding: 16px;
}
.modal-card {
position: relative;
background: #ffffff;
border-radius: 24px;
max-width: 900px;
width: 100%;
max-height: 90vh;
overflow-y: auto;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
border: 1px solid rgba(255, 255, 255, 0.2);
}
.modal-close-btn {
position: absolute;
top: 16px;
right: 16px;
width: 36px;
height: 36px;
border-radius: 50%;
background: #f1f5f9;
border: none;
font-size: 1.1rem;
color: #475569;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
z-index: 20;
transition: all 0.2s ease;
}
.modal-close-btn:hover {
background: #e2e8f0;
color: #0f172a;
}
.modal-grid {
display: grid;
grid-template-columns: 1fr;
}
@media (min-width: 768px) {
.modal-grid {
grid-template-columns: 1fr 1.15fr;
}
}
.modal-img-col {
position: relative;
background: #0f172a;
display: flex;
align-items: center;
justify-content: center;
min-height: 300px;
}
.modal-main-img {
width: 100%;
height: 100%;
max-height: 520px;
object-fit: cover;
display: block;
}
.modal-img-badge {
position: absolute;
top: 16px;
left: 16px;
background: var(--accent-color, #d97706);
color: #ffffff;
font-size: 0.75rem;
font-weight: 800;
padding: 5px 12px;
border-radius: 9999px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
.modal-content-col {
padding: clamp(24px, 4vw, 36px);
display: flex;
flex-direction: column;
justify-content: space-between;
}
.modal-pill {
display: inline-block;
font-size: 0.75rem;
font-weight: 700;
color: var(--primary-color, #1e3a8a);
background: rgba(30, 58, 138, 0.08);
padding: 4px 10px;
border-radius: 9999px;
margin-bottom: 8px;
}
.modal-title {
font-size: clamp(1.4rem, 3vw, 1.85rem);
font-weight: 900;
color: #0f172a;
letter-spacing: -0.5px;
line-height: 1.25;
}
.modal-title .text-sub {
display: block;
font-size: 1rem;
font-weight: 700;
color: var(--primary-color, #1e3a8a);
margin-top: 4px;
}
.modal-slogan {
font-size: 0.88rem;
color: #475569;
margin-top: 8px;
line-height: 1.5;
word-break: keep-all;
}
.modal-points {
margin: 20px 0;
display: flex;
flex-direction: column;
gap: 12px;
background: #f8fafc;
padding: 16px;
border-radius: 16px;
border: 1px solid #e2e8f0;
}
.point-row {
display: flex;
gap: 12px;
align-items: flex-start;
}
.point-num {
font-size: 0.85rem;
font-weight: 900;
color: var(--primary-color, #1e3a8a);
background: #ffffff;
padding: 2px 8px;
border-radius: 6px;
border: 1px solid #cbd5e1;
flex-shrink: 0;
}
.point-head {
display: block;
font-size: 0.88rem;
font-weight: 800;
color: #1e293b;
margin-bottom: 2px;
}
.point-body {
font-size: 0.78rem;
color: #64748b;
line-height: 1.45;
word-break: keep-all;
}
.modal-actions {
display: flex;
gap: 10px;
flex-wrap: wrap;
margin-top: 10px;
}
.btn-modal-apply {
flex: 1 1 200px;
background: var(--primary-color, #1e3a8a);
color: #ffffff;
font-size: 0.92rem;
font-weight: 800;
padding: 14px 20px;
border-radius: 14px;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 14px rgba(30, 58, 138, 0.25);
transition: all 0.2s ease;
}
.btn-modal-apply:hover {
filter: brightness(1.1);
transform: translateY(-2px);
}
.btn-modal-link {
background: #f1f5f9;
color: #334155;
font-size: 0.85rem;
font-weight: 700;
padding: 14px 18px;
border-radius: 14px;
border: 1px solid #cbd5e1;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
}
.btn-modal-link:hover {
background: #e2e8f0;
color: #0f172a;
}
/* 모달 트랜지션 */
.modal-fade-enter-active,
.modal-fade-leave-active {
transition: opacity 0.3s ease;
}
.modal-fade-enter-from,
.modal-fade-leave-to {
opacity: 0;
}
.modal-fade-enter-active .modal-card,
.modal-fade-leave-active .modal-card {
transition: transform 0.3s cubic-bezier(0.25, 1, 0.5, 1);
}
.modal-fade-enter-from .modal-card,
.modal-fade-leave-to .modal-card {
transform: scale(0.92) translateY(20px);
}
</style>
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 MiB

+7
View File
@@ -62,6 +62,13 @@
:subjectName="parsed.subjectName" :subjectName="parsed.subjectName"
/> />
<!-- 12. 과목별 1타 강사진 갤러리 캐러셀 (클릭 시 페이지 모달 확대 및 상담 연동) -->
<SubjectCarousel
:regionDong="parsed.dong"
:grade="parsed.grade"
:currentSubject="parsed.subjectName"
/>
<!-- 웹 광고 단일 목적: 해당 학년과 과목이 기본 선택된 무료 상담 신청 폼 --> <!-- 웹 광고 단일 목적: 해당 학년과 과목이 기본 선택된 무료 상담 신청 폼 -->
<ConsultForm <ConsultForm
:regionName="parsed.shortRegionName" :regionName="parsed.shortRegionName"
+4 -15
View File
@@ -1,5 +1,5 @@
<template> <template>
<div class="landing-container bg-[#F0FDF4] text-slate-800 antialiased relative pb-24 md:pb-12 min-h-screen w-full"> <div class="landing-container bg-[#F0FDF4] text-slate-800 antialiased relative pb-8 min-h-screen w-full">
<!-- Header --> <!-- Header -->
<header class="bg-white border-b border-slate-200 sticky top-0 z-40 shadow-sm w-full"> <header class="bg-white border-b border-slate-200 sticky top-0 z-40 shadow-sm w-full">
@@ -330,6 +330,9 @@
</div> </div>
</section> </section>
<!-- 과목별 1:1 맞춤과외 갤러리 캐러셀 (클릭 시 확대 모달 및 상담/이동) -->
<SubjectCarousel grade="초·중·고" />
<!-- FAQ 섹션 --> <!-- FAQ 섹션 -->
<section class="mt-16 px-4 sm:px-6 max-w-4xl mx-auto"> <section class="mt-16 px-4 sm:px-6 max-w-4xl mx-auto">
<header class="text-center mb-8"> <header class="text-center mb-8">
@@ -353,20 +356,6 @@
</main> </main>
<!-- 하단 모바일 고정 CTA 바 -->
<aside class="fixed bottom-0 left-0 right-0 bg-white/95 backdrop-blur-md border-t border-slate-200 p-3 sm:p-4 z-40 shadow-2xl">
<div class="max-w-4xl mx-auto flex items-center gap-3">
<a href="tel:010-5961-5807" class="flex flex-col items-center justify-center px-4 py-2.5 bg-slate-100 hover:bg-slate-200 text-slate-800 rounded-xl text-xs font-bold shrink-0 transition" title="전화상담">
<i class="fa-solid fa-phone text-emerald-700 text-sm mb-0.5"></i>
<span>010-5961-5807</span>
</a>
<a href="#leadFormSection" class="flex-1 bg-gradient-to-r from-emerald-600 via-teal-600 to-emerald-600 hover:opacity-95 text-white font-extrabold text-sm sm:text-base py-3 sm:py-3.5 px-4 rounded-xl shadow-lg transition flex items-center justify-center gap-2">
<i class="fa-solid fa-seedling text-xs sm:text-sm"></i>
<span>지금 무료 습관 진단 & 멘토 신청하기</span>
</a>
</div>
</aside>
</div> </div>
</template> </template>
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 MiB

+1 -1
View File
@@ -30,7 +30,7 @@ export default defineEventHandler(async (event) => {
const webhookUrl = config.discordWebhookUrl || 'https://discordapp.com/api/webhooks/1557204310369116210/9J4y96kmSbYNGtw5OxRgIz7InWcM8o3f8UX0Ad71-IyofwdS7tWmXkF7dj457-I8Ypiu' const webhookUrl = config.discordWebhookUrl || 'https://discordapp.com/api/webhooks/1557204310369116210/9J4y96kmSbYNGtw5OxRgIz7InWcM8o3f8UX0Ad71-IyofwdS7tWmXkF7dj457-I8Ypiu'
const siteName = config.public.siteName || '1:1 맞춤과외' const siteName = config.public.siteName || '1:1 맞춤과외'
const siteDomain = config.public.siteDomain || 'https://aeseo.cloud' const siteDomain = config.public.siteDomain || 'https://aeseo.shop'
// 한국 시간 (KST) // 한국 시간 (KST)
const now = new Date() const now = new Date()
-1
View File
@@ -96,7 +96,6 @@ export function getShortRegionName(sido: string, dong: string, sigungu?: string)
} }
// 경기, 인천, 광주, 부산, 대구, 대전 (예: 경기 수원 영통동, 대구 수성구 범어동) // 경기, 인천, 광주, 부산, 대구, 대전 (예: 경기 수원 영통동, 대구 수성구 범어동)
return `${prefix}${sigungu ? sigungu + ' ' : ''}${dong || ''}`.trim() return `${prefix}${sigungu ? sigungu + ' ' : ''}${dong || ''}`.trim()
} ${dong || ''}`.trim()
} }
// 지능형 URL 슬러그 파서 // 지능형 URL 슬러그 파서
+6 -2
View File
@@ -5,8 +5,12 @@ export function generateSeoMeta(parsed: ParsedRouteParams, siteName = '새솔 1:
const { sido, sigungu, dong, shortRegionName, grade, subjectName, targetTerm, fullKeyword } = parsed const { sido, sigungu, dong, shortRegionName, grade, subjectName, targetTerm, fullKeyword } = parsed
const regionTitle = shortRegionName || getShortRegionName(sido, dong) const regionTitle = shortRegionName || getShortRegionName(sido, dong)
const pageTitle = `${regionTitle} ${grade} ${subjectName} 과외 | ${dong} 내신·수능 1:1 맞춤수업 - ${siteName}`
const pageDescription = `${sido} ${sigungu} ${dong} 지역 초·중·고 ${grade} ${subjectName} 1:1 전문 과외. 인근 학교별 기출 족보 완벽 분석, 서술형 감점 방지, 취약 개념 클리닉 및 맞춤 학습 플래너 제공. 지금 ${dong} 무료 학습 진단 및 모의수업을 신청하세요.` // 학부모 검색 최적화: [지역] [과목]과외 전문 매칭 | [학년] 1:1 방문 맞춤 수업 (공백 포함 30~35자 내외 말줄임 방지)
const pageTitle = `${regionTitle} ${subjectName}과외 전문 매칭 | ${grade} 1:1 방문 맞춤 수업`
// 고의도 검색 및 전환 최적화 메타 디스크립션 (과외 비용 시세 + 학교 기출 분석 + 100% 신원 검증 + 무료 시범수업)
const pageDescription = `${regionTitle} ${grade} ${subjectName}과외 전문 매칭. 과외 비용 및 시세 비교부터 무료 시범수업 신청까지. ${dong} 인근 학교별 기출 족보 완벽 분석, 서술형 감점 방지, 검증된 1:1 전문 선생님 100% 매칭.`
// 표준 Canonical URL // 표준 Canonical URL
const canonicalUrl = `${siteDomain}/${encodeURIComponent(dong)}-${encodeURIComponent(grade)}-${encodeURIComponent(subjectName)}` const canonicalUrl = `${siteDomain}/${encodeURIComponent(dong)}-${encodeURIComponent(grade)}-${encodeURIComponent(subjectName)}`
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

+7 -3
View File
@@ -178,7 +178,7 @@ const handleSubmit = async () => {
try { try {
const currentUrl = typeof window !== 'undefined' ? window.location.href : '' const currentUrl = typeof window !== 'undefined' ? window.location.href : ''
await $fetch('/api/consult', { const res = await $fetch('/api/consult', {
method: 'POST', method: 'POST',
body: { body: {
studentName: form.value.studentName, studentName: form.value.studentName,
@@ -190,10 +190,14 @@ const handleSubmit = async () => {
url: currentUrl url: currentUrl
} }
}) })
if (res && res.success) {
submitted.value = true submitted.value = true
} else {
alert('상담 신청 접수 중 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.')
}
} catch (err) { } catch (err) {
console.error('상담 신청 전송:', err) console.error('상담 신청 전송 실패:', err)
submitted.value = true alert('상담 신청 접수 중 문제가 발생했습니다. 전화(010-5961-5807)로 문의해 주시기 바랍니다.')
} finally { } finally {
loading.value = false loading.value = false
} }
+78 -177
View File
@@ -1,39 +1,89 @@
<template> <template>
<header class="hero-banner"> <header class="hero-banner-clean bg-white border-b border-slate-200/80 pt-10 sm:pt-14 pb-14 sm:pb-18 px-4 sm:px-6 relative overflow-hidden text-center">
<div class="hero-container">
<div class="hero-badge-wrap"> <!-- 은은한 상단 엠비언트 라이트 -->
<span class="hero-badge royal-badge">{{ region.dong }} 학군 맞춤 1:1 전문 지도</span> <div class="absolute inset-0 bg-gradient-to-b from-blue-50/40 via-transparent to-transparent pointer-events-none"></div>
<span class="hero-subbadge">2026 개정 교육과정 완벽 반영</span>
<div class="max-w-4xl mx-auto relative z-10">
<!-- 신뢰 보증 뱃지 -->
<div class="inline-flex items-center gap-2 px-3.5 py-1.5 rounded-full text-xs font-semibold bg-slate-50 border border-slate-200 text-slate-700 shadow-xs mb-5">
<span class="w-2 h-2 rounded-full bg-blue-600"></span>
<span>{{ region.dong }} 학군 전담 | 서울대·연고대 및 베테랑 강사진 100% 신원 보증</span>
</div> </div>
<h1 class="hero-title"> <!-- SEO 메인 H1 (사용자 지정 롱테일 조합형: [지역] + [학년] + [과목]과외 + 검증된 전문 선생님 100% 매칭) -->
<span class="region-highlight">{{ displayRegionName }}</span><br /> <h1 class="text-2xl sm:text-4xl md:text-5xl font-extrabold tracking-tight text-slate-900 leading-[1.22] sm:leading-[1.18] mb-4">
<span class="subject-highlight">{{ grade }} {{ subjectName }}</span> 1:1 맞춤 과외 <span>{{ displayRegionName }} {{ grade }} {{ subjectName }}과외</span><br />
<span class="text-blue-600">우리 아이 맞춤 검증된 전문 선생님 100% 매칭</span>
</h1> </h1>
<p class="hero-desc"> <!-- 서브 카피 (비용 시세 비교 + 학교 기출 분석 + 무료 시범수업 신뢰 트리거) -->
{{ region.dong }} 인근 학교별 기출 분석부터 서술형 조건 감점 0점화까지!<br /> <p class="text-xs sm:text-base text-slate-600 font-normal max-w-2xl mx-auto leading-relaxed mb-7">
우리 아이의 취약점을 1:1로 진단하고 <strong>성적 1등급 역전</strong>을 이끌어냅니다. {{ region.dong }} 인근 학교별 기출 분석부터 과외 비용·시세 비교, 취약 개념 클리닉까지.<br class="hidden sm:inline" />
직접 수업받아보고 결정하는 <strong>1:1 무료 방문·화상 시범수업</strong>을 신청하세요.
</p> </p>
<div class="hero-cta-group"> <!-- 4대 핵심 신뢰 지표 바 -->
<a href="#consult-section" class="btn-hero-primary"> <div class="grid grid-cols-2 md:grid-cols-4 gap-2.5 sm:gap-3 max-w-3xl mx-auto mb-7 text-left">
<span>{{ region.dong }} 1:1 무료 방문·진단 모의수업 신청</span> <div class="bg-slate-50 border border-slate-200/90 rounded-xl p-3 flex items-start gap-2.5">
</a> <i class="fa-solid fa-circle-check text-blue-600 text-sm sm:text-base mt-0.5 shrink-0"></i>
<div class="hero-call-info"> <div>
<span class="call-icon"></span> <strong class="block text-xs sm:text-sm font-bold text-slate-900">100% 서류 검증</strong>
<span class="call-text">실시간 학습상담 <strong>010-5961-5807</strong></span> <span class="text-[11px] text-slate-500 leading-tight">학력·경력 증명서 인증</span>
</div> </div>
</div> </div>
<div class="hero-tags"> <div class="bg-slate-50 border border-slate-200/90 rounded-xl p-3 flex items-start gap-2.5">
<span class="tag-item">#{{ region.dong }}과외</span> <i class="fa-solid fa-circle-check text-blue-600 text-sm sm:text-base mt-0.5 shrink-0"></i>
<span class="tag-item">#{{ region.dong }}{{ subjectName }}</span> <div>
<span class="tag-item">#{{ grade }}내신대비</span> <strong class="block text-xs sm:text-sm font-bold text-slate-900">무료 시범수업</strong>
<span class="tag-item">#서술형감점방지</span> <span class="text-[11px] text-slate-500 leading-tight">직접 받아보고 선택</span>
<span class="tag-item">#1대1밀착코칭</span>
</div> </div>
</div> </div>
<div class="bg-slate-50 border border-slate-200/90 rounded-xl p-3 flex items-start gap-2.5">
<i class="fa-solid fa-circle-check text-blue-600 text-sm sm:text-base mt-0.5 shrink-0"></i>
<div>
<strong class="block text-xs sm:text-sm font-bold text-slate-900">과외 비용 투명 시세</strong>
<span class="text-[11px] text-slate-500 leading-tight">동네 표준 시세 가이드</span>
</div>
</div>
<div class="bg-slate-50 border border-slate-200/90 rounded-xl p-3 flex items-start gap-2.5">
<i class="fa-solid fa-circle-check text-blue-600 text-sm sm:text-base mt-0.5 shrink-0"></i>
<div>
<strong class="block text-xs sm:text-sm font-bold text-slate-900">학교별 기출 분석</strong>
<span class="text-[11px] text-slate-500 leading-tight">{{ region.dong }} 3개년 족보 완파</span>
</div>
</div>
</div>
<!-- CTA 그룹 -->
<div class="flex flex-col items-center gap-3.5 mb-6">
<a
href="#consult-section"
class="inline-flex items-center justify-center gap-2 w-full max-w-md py-4 px-6 bg-blue-600 hover:bg-blue-700 text-white font-extrabold text-sm sm:text-base rounded-xl shadow-md hover:shadow-lg transition-all"
>
<i class="fa-solid fa-file-signature text-base"></i>
<span>{{ region.dong }} 과외 시세 확인 & 무료 시범수업 신청</span>
</a>
<div class="flex items-center gap-2 text-xs sm:text-sm text-slate-500">
<i class="fa-solid fa-phone text-blue-600 text-xs"></i>
<span>실시간 학습상담 직통: <strong class="text-slate-800 font-bold">010-5961-5807</strong></span>
</div>
</div>
<!-- 태그 목록 -->
<div class="flex justify-center flex-wrap gap-1.5">
<span class="text-[11px] px-2.5 py-1 bg-slate-100 border border-slate-200 text-slate-600 rounded-md font-medium">#{{ region.dong }}과외</span>
<span class="text-[11px] px-2.5 py-1 bg-slate-100 border border-slate-200 text-slate-600 rounded-md font-medium">#{{ region.dong }}{{ subjectName }}과외</span>
<span class="text-[11px] px-2.5 py-1 bg-slate-100 border border-slate-200 text-slate-600 rounded-md font-medium">#{{ grade }}내신대비</span>
<span class="text-[11px] px-2.5 py-1 bg-slate-100 border border-slate-200 text-slate-600 rounded-md font-medium">#과외비용시세</span>
<span class="text-[11px] px-2.5 py-1 bg-slate-100 border border-slate-200 text-slate-600 rounded-md font-medium">#1대1무료시범수업</span>
</div>
</div>
</header> </header>
</template> </template>
@@ -55,11 +105,10 @@ const props = defineProps({
}, },
subjectName: { subjectName: {
type: String, type: String,
default: '영어' default: '수학'
} }
}) })
// '대구광역시 수성구 황금동' -> '대구 황금동' 등 축약 지역명 산출
const displayRegionName = computed(() => { const displayRegionName = computed(() => {
if (props.shortRegionName) return props.shortRegionName if (props.shortRegionName) return props.shortRegionName
if (props.region) { if (props.region) {
@@ -74,165 +123,17 @@ const displayRegionName = computed(() => {
else if (sido.includes('광주')) shortSido = '광주' else if (sido.includes('광주')) shortSido = '광주'
else if (sido.includes('대전')) shortSido = '대전' else if (sido.includes('대전')) shortSido = '대전'
else if (sido.includes('울산')) shortSido = '울산' else if (sido.includes('울산')) shortSido = '울산'
else if (sido.includes('세종')) shortSido = '세종'
else if (sido.includes('경기')) shortSido = '경기' else if (sido.includes('경기')) shortSido = '경기'
else if (sido.includes('강원')) shortSido = '강원' return `${shortSido} ${dong}`
else if (sido.includes('충북') || sido.includes('충청북')) shortSido = '충북'
else if (sido.includes('충남') || sido.includes('충청남')) shortSido = '충남'
else if (sido.includes('전북') || sido.includes('전라북')) shortSido = '전북'
else if (sido.includes('전남') || sido.includes('전라남')) shortSido = '전남'
else if (sido.includes('경북') || sido.includes('경상북')) shortSido = '경북'
else if (sido.includes('경남') || sido.includes('경상남')) shortSido = '경남'
else if (sido.includes('제주')) shortSido = '제주'
return `${shortSido} ${dong}`.trim()
} }
return props.region.fullName || '' return dong || sido
} }
return '' return ''
}) })
</script> </script>
<style scoped> <style scoped>
.hero-banner { .hero-banner-clean {
background: var(--hero-gradient, linear-gradient(135deg, #0f172a 0%, #1e3a8a 100%));
color: #ffffff;
padding: clamp(40px, 8vw, 80px) 16px clamp(35px, 6vw, 60px);
text-align: center;
position: relative;
overflow: hidden;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
}
.hero-banner::before {
content: "";
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background: radial-gradient(circle at 50% 20%, rgba(217, 119, 6, 0.15) 0%, transparent 60%);
pointer-events: none;
}
.hero-container {
max-width: 900px;
margin: 0 auto;
position: relative;
z-index: 1;
}
.hero-badge-wrap {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
flex-wrap: wrap;
margin-bottom: 20px;
}
.hero-badge {
display: inline-block;
padding: 6px 14px;
font-size: clamp(0.78rem, 2.2vw, 0.9rem);
font-weight: 700;
border-radius: 9999px;
background: var(--accent-color, #d97706);
color: #ffffff;
letter-spacing: -0.3px;
}
.hero-subbadge {
display: inline-block;
padding: 6px 12px;
font-size: clamp(0.75rem, 2vw, 0.85rem);
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(4px);
border-radius: 9999px;
color: #e2e8f0;
}
.hero-title {
font-size: clamp(1.65rem, 5vw, 2.85rem);
font-weight: 900;
line-height: 1.3;
margin-bottom: 18px;
word-break: keep-all; word-break: keep-all;
letter-spacing: -0.8px;
}
.region-highlight {
color: var(--hero-region-color, #cbd5e1);
font-size: 0.85em;
font-weight: 700;
}
.subject-highlight {
color: var(--accent-light, #fbbf24);
text-decoration: underline;
text-underline-offset: 6px;
}
.hero-desc {
font-size: clamp(0.92rem, 2.6vw, 1.15rem);
line-height: 1.65;
color: #e2e8f0;
margin-bottom: 30px;
word-break: keep-all;
}
.hero-cta-group {
display: flex;
flex-direction: column;
align-items: center;
gap: 14px;
margin-bottom: 26px;
}
.btn-hero-primary {
display: inline-flex;
align-items: center;
justify-content: center;
padding: clamp(14px, 3.5vw, 18px) clamp(20px, 5vw, 36px);
font-size: clamp(0.95rem, 2.8vw, 1.2rem);
font-weight: 800;
color: #ffffff;
background: var(--hero-btn-bg, linear-gradient(135deg, #d97706 0%, #b45309 100%));
border-radius: var(--card-radius, 12px);
box-shadow: 0 8px 24px rgba(217, 119, 6, 0.35);
transition: transform 0.2s ease, box-shadow 0.2s ease;
width: 100%;
max-width: 480px;
min-height: 48px;
}
.btn-hero-primary:hover {
transform: translateY(-2px);
box-shadow: 0 12px 28px rgba(217, 119, 6, 0.45);
}
.hero-call-info {
display: flex;
align-items: center;
gap: 6px;
font-size: clamp(0.85rem, 2.2vw, 0.95rem);
color: #cbd5e1;
}
.hero-call-info strong {
color: #ffffff;
font-size: 1.1em;
}
.hero-tags {
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 6px;
}
.tag-item {
font-size: clamp(0.72rem, 1.8vw, 0.82rem);
padding: 4px 10px;
background: rgba(255, 255, 255, 0.08);
border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 6px;
color: #cbd5e1;
} }
</style> </style>
+783
View File
@@ -0,0 +1,783 @@
<template>
<section class="subject-gallery-section" aria-label="과목별 1:1 맞춤과외 갤러리">
<div class="gallery-container">
<!-- 섹션 헤더 -->
<div class="gallery-header">
<span class="gallery-badge">
<i class="fa-solid fa-sparkles mr-1"></i>
{{ regionDong ? `${regionDong} ` : '' }}과목별 1:1 전문 전담팀
</span>
<h2 class="gallery-title">
취약 과목을 1등급 전략 과목으로 역전시키는<br />
<strong>1:1 전담 과목별 클래스</strong>
</h2>
<p class="gallery-desc">
원하시는 과목 카드를 클릭하시면 1:1 맞춤 커리큘럼과 상세 안내를 페이지에서 크게 확인하실 수 있습니다.
</p>
</div>
<!-- 2 - 2 - 1 그리드 정렬 레이아웃 -->
<div class="subject-grid-221">
<div
v-for="(item, idx) in subjectList"
:key="item.name"
class="gallery-card"
:class="`card-item-${idx + 1}`"
@click="openModal(item)"
>
<div class="card-inner">
<div class="img-wrap">
<img
:src="item.image"
:alt="`${item.name} 1:1 맞춤 지도`"
class="subject-img"
loading="lazy"
/>
<span class="subject-tag">{{ item.tag }}</span>
<div class="zoom-overlay">
<span class="zoom-btn">
<i class="fa-solid fa-magnifying-glass-plus"></i>
<span>상세 보기</span>
</span>
</div>
</div>
<div class="card-info">
<div class="card-subject-name">
<span class="sub-name">{{ item.name }}</span>
<span class="sub-grade">{{ grade }}</span>
</div>
<p class="card-subject-desc">{{ item.desc }}</p>
<div class="card-action">
<span>자세히 보기 & 신청</span>
<i class="fa-solid fa-arrow-right"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 클릭 시 페이지에 크게 나오는 상세 모달 (Lightbox Modal) -->
<Teleport to="body">
<Transition name="modal-fade">
<div
v-if="selectedItem"
class="modal-backdrop"
@click.self="closeModal"
role="dialog"
aria-modal="true"
>
<div class="modal-card">
<!-- 닫기 버튼 -->
<button
type="button"
class="modal-close-btn"
@click="closeModal"
aria-label="닫기"
>
<i class="fa-solid fa-xmark"></i>
</button>
<div class="modal-grid">
<!-- 모달 좌측: 고해상도 생성 이미지 원본 -->
<div class="modal-img-col">
<img
:src="selectedItem.image"
:alt="`${selectedItem.name} 1:1 맞춤 과외`"
class="modal-main-img"
/>
<span class="modal-img-badge">{{ selectedItem.tag }}</span>
</div>
<!-- 모달 우측: 상세 설명 및 액션 버튼 -->
<div class="modal-content-col">
<div class="modal-header">
<span class="modal-pill">{{ regionDong || '관내' }} 1:1 밀착 코칭</span>
<h3 class="modal-title">
{{ selectedItem.name }}
<span class="text-sub">1:1 맞춤 마스터 클래스</span>
</h3>
<p class="modal-slogan">{{ selectedItem.slogan }}</p>
</div>
<div class="modal-points">
<div class="point-row" v-for="(pt, pIdx) in selectedItem.details" :key="pIdx">
<span class="point-num">0{{ pIdx + 1 }}</span>
<div>
<strong class="point-head">{{ pt.title }}</strong>
<p class="point-body">{{ pt.desc }}</p>
</div>
</div>
</div>
<!-- 모달 하단 액션 버튼 그룹 -->
<div class="modal-actions">
<button
type="button"
class="btn-modal-apply"
@click="applyWithSubject(selectedItem.name)"
>
<i class="fa-solid fa-paper-plane mr-2"></i>
<span>{{ selectedItem.name }} 무료 상담 신청하기</span>
</button>
<button
type="button"
class="btn-modal-link"
@click="goToSubjectPage(selectedItem.subjectKey)"
>
<span>전용 페이지 이동</span>
<i class="fa-solid fa-chevron-right ml-1"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</Transition>
</Teleport>
</section>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
const props = defineProps({
regionDong: {
type: String,
default: ''
},
grade: {
type: String,
default: '중·고등'
},
currentSubject: {
type: String,
default: ''
}
})
const router = useRouter()
// 5대 핵심 과목 (2 2 1 순서 배치)
const subjectList = [
// 1행: 수학, 영어
{
name: '수학과외',
subjectKey: 'math',
tag: '인기 1위',
image: '/img/수학과외.png',
desc: '개념 구멍 추적 및 킬러 문항 1:1 완파',
slogan: '단순 공식 암기가 아닌 원리 이해와 킬러 문항 해결력을 기릅니다.',
details: [
{ title: '오답 4분류 역추적 클리닉', desc: '자주 실수하는 계산 오류 및 조건 누락 패턴을 1:1로 교정합니다.' },
{ title: '학교별 3개년 기출 족보 변형', desc: '인근 학교의 빈출 고난도 서술형 문항을 시험 전 3회 이상 체화합니다.' },
{ title: '50분 실전 타임어택 훈련', desc: '실제 시험 시간 부족을 해결하기 위해 문항별 시간 배분 루틴을 훈련합니다.' }
]
},
{
name: '영어과외',
subjectKey: 'english',
tag: '내신 필수',
image: '/img/영어과외.png',
desc: '교과서·부교재 전 지문 변형 및 서술형 영작',
slogan: '어휘, 문법, 서술형 감점 0점화로 내신 1등급을 완성합니다.',
details: [
{ title: '부교재 전 지문 어휘·문맥 변형', desc: '수능특강, 모의고사 기출 등 학교 부교재의 변형 출제 포인트를 완벽 대비합니다.' },
{ title: '서술형 조건 영작 1:1 첨삭', desc: '문법 조건 누락 감점을 원천 차단하는 정밀 첨삭 지도를 진행합니다.' },
{ title: '1:1 구문 독해 & 빈칸 추론 특훈', desc: '문장 구조 분석을 통해 킬러 빈칸·순서 배열 문제를 빠르고 정확히 풉니다.' }
]
},
// 2행: 국어, 과학
{
name: '국어과외',
subjectKey: 'korean',
tag: '문해력 완성',
image: '/img/국어과외.png',
desc: '비문학 독해 논리와 교과서 문학 1:1 정밀 분석',
slogan: '긴 지문도 흔들리지 않는 문해력과 서술형 채점 기준을 공략합니다.',
details: [
{ title: '비문학 구조 독해 공식 전수', desc: '제재별 핵심 키워드 연결과 선지 근거 찾기 훈련을 1:1로 코칭합니다.' },
{ title: '교과서 및 외부 지문 연계 분석', desc: '낯선 현대시·고전시가도 스스로 해석할 수 있는 감상 원리를 터득합니다.' },
{ title: '서술형 핵심 키워드 채점표 정복', desc: '출제자가 요구하는 조건에 맞춘 군더더기 없는 완벽한 답안 작성을 훈련합니다.' }
]
},
{
name: '과학과외',
subjectKey: 'science',
tag: '통합과학',
image: '/img/과학과외.png',
desc: '통합과학 원리 이해 및 물화생지 킬러 단원 정복',
slogan: '까다로운 계산과 복잡한 개념을 1:1 시각화와 원리 풀이로 해결합니다.',
details: [
{ title: '2026 개정 통합과학 개념 체계화', desc: '교과 단원 간 융합 개념을 알기 쉽게 정리하고 탐구형 문항을 대비합니다.' },
{ title: '물화생지 킬러 계산 단원 완파', desc: '역학, 화학 반응식, 유전 등 학생들이 가장 어려워하는 단원을 집중 지도합니다.' },
{ title: '수행평가 실험 보고서 1:1 가이드', desc: '지필고사뿐 아니라 감점되기 쉬운 과학 탐구 보고서 만점을 케어합니다.' }
]
},
// 3행: 사회 (1개 단독 센터 정렬)
{
name: '사회과외',
subjectKey: 'social',
tag: '통합사회',
image: '/img/사회과외.png',
desc: '통합사회·한국사 핵심 흐름 및 사탐 만점 전략',
slogan: '무작정 외우지 않고 역사와 사회 현상의 맥락을 이해하며 1등급을 쟁취합니다.',
details: [
{ title: '시대별 흐름 마인드맵 정리', desc: '단편적 암기가 아닌 전후 인과관계를 입체적으로 정리해 기억을 오래 유지합니다.' },
{ title: '자료 해석 및 그래프 변형 문항 정복', desc: '사탐 킬러로 출제되는 지도·통계·사료 분석 능력을 1:1로 키워줍니다.' },
{ title: '단기 서술형 족보 총정리', desc: '시험 3주 전 핵심 키워드와 단원별 요약 노트를 통해 내신 만점을 달성합니다.' }
]
}
]
const selectedItem = ref(null)
// 모달 오픈/클로즈
const openModal = (item) => {
selectedItem.value = item
if (typeof document !== 'undefined') {
document.body.style.overflow = 'hidden'
}
}
const closeModal = () => {
selectedItem.value = null
if (typeof document !== 'undefined') {
document.body.style.overflow = ''
}
}
// 모달 내 과목 선택 후 상담 신청 폼으로 이동
const applyWithSubject = (subjectName) => {
closeModal()
const cleanSubj = subjectName.replace(/과외$/, '')
const subjSelect = document.getElementById('weakSubject') || document.getElementById('c-subject')
if (subjSelect) {
subjSelect.value = cleanSubj
subjSelect.dispatchEvent(new Event('change'))
}
const formTarget = document.getElementById('leadFormSection') || document.getElementById('consult-section')
if (formTarget) {
formTarget.scrollIntoView({ behavior: 'smooth' })
}
}
// 해당 과목 전용 페이지로 이동
const goToSubjectPage = (subjectKey) => {
closeModal()
const dong = props.regionDong || '서울'
const grade = props.grade || '중학생'
const subMap = {
math: '수학',
english: '영어',
korean: '국어',
science: '과학',
social: '사회'
}
const subName = subMap[subjectKey] || '수학'
const targetUrl = `/${encodeURIComponent(dong)}-${encodeURIComponent(grade)}-${encodeURIComponent(subName)}`
router.push(targetUrl)
}
// ESC 키로 모달 닫기
const handleKeyDown = (e) => {
if (e.key === 'Escape' && selectedItem.value) {
closeModal()
}
}
onMounted(() => {
if (typeof window !== 'undefined') {
window.addEventListener('keydown', handleKeyDown)
}
})
onUnmounted(() => {
if (typeof window !== 'undefined') {
window.removeEventListener('keydown', handleKeyDown)
document.body.style.overflow = ''
}
})
</script>
<style scoped>
.subject-gallery-section {
width: 100%;
max-width: 1080px;
margin: 40px auto 60px;
padding: 0 16px;
position: relative;
box-sizing: border-box;
}
.gallery-container {
background: linear-gradient(180deg, #ffffff 0%, #f8fafc 100%);
border: 1px solid #e2e8f0;
border-radius: 28px;
padding: clamp(24px, 4vw, 44px) clamp(16px, 3vw, 36px);
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.05);
}
.gallery-header {
text-align: center;
margin-bottom: 32px;
}
.gallery-badge {
display: inline-flex;
align-items: center;
font-size: clamp(0.78rem, 2vw, 0.88rem);
font-weight: 700;
color: var(--primary-color, #1e3a8a);
background: rgba(30, 58, 138, 0.08);
padding: 6px 14px;
border-radius: 9999px;
margin-bottom: 10px;
}
.gallery-title {
font-size: clamp(1.35rem, 3.5vw, 1.95rem);
font-weight: 800;
color: #0f172a;
line-height: 1.35;
letter-spacing: -0.5px;
margin-bottom: 8px;
}
.gallery-title strong {
color: var(--primary-color, #1e3a8a);
}
.gallery-desc {
font-size: clamp(0.82rem, 2vw, 0.94rem);
color: #64748b;
word-break: keep-all;
}
/* 2 - 2 - 1 그리드 레이아웃 */
.subject-grid-221 {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
width: 100%;
}
/* 5번째 아이템: 3행 단독 1개 (2열 span 및 중앙 정렬) */
.card-item-5 {
grid-column: 1 / -1;
justify-self: center;
width: 100%;
max-width: calc(50% - 10px);
}
.gallery-card {
cursor: pointer;
border-radius: 20px;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
}
.card-inner {
background: #ffffff;
border-radius: 20px;
overflow: hidden;
border: 1px solid #e2e8f0;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.04);
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
display: flex;
flex-direction: column;
height: 100%;
}
.gallery-card:hover .card-inner {
transform: translateY(-6px);
box-shadow: 0 16px 32px rgba(30, 58, 138, 0.12);
border-color: #93c5fd;
}
.img-wrap {
position: relative;
width: 100%;
aspect-ratio: 1 / 1;
overflow: hidden;
background: #f1f5f9;
}
.subject-img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.5s ease;
}
.gallery-card:hover .subject-img {
transform: scale(1.05);
}
.subject-tag {
position: absolute;
top: 14px;
left: 14px;
background: rgba(15, 23, 42, 0.85);
backdrop-filter: blur(4px);
color: #ffffff;
font-size: 0.75rem;
font-weight: 800;
padding: 4px 12px;
border-radius: 9999px;
z-index: 2;
}
.zoom-overlay {
position: absolute;
inset: 0;
background: rgba(15, 23, 42, 0.4);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
z-index: 3;
}
.gallery-card:hover .zoom-overlay {
opacity: 1;
}
.zoom-btn {
background: #ffffff;
color: #0f172a;
font-size: 0.88rem;
font-weight: 800;
padding: 10px 18px;
border-radius: 9999px;
display: inline-flex;
align-items: center;
gap: 6px;
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
transform: translateY(6px);
transition: transform 0.3s ease;
}
.gallery-card:hover .zoom-btn {
transform: translateY(0);
}
.card-info {
padding: 18px 20px;
display: flex;
flex-direction: column;
flex: 1;
}
.card-subject-name {
display: flex;
align-items: baseline;
gap: 8px;
margin-bottom: 6px;
}
.sub-name {
font-size: 1.2rem;
font-weight: 800;
color: #0f172a;
}
.sub-grade {
font-size: 0.78rem;
font-weight: 700;
color: #64748b;
background: #f1f5f9;
padding: 2px 8px;
border-radius: 6px;
}
.card-subject-desc {
font-size: 0.85rem;
color: #475569;
line-height: 1.45;
margin-bottom: 14px;
flex: 1;
word-break: keep-all;
}
.card-action {
font-size: 0.82rem;
font-weight: 700;
color: var(--primary-color, #1e3a8a);
display: flex;
align-items: center;
gap: 6px;
transition: gap 0.2s ease;
}
.gallery-card:hover .card-action {
gap: 10px;
}
/* 모바일 반응형 대응 */
@media (max-width: 640px) {
.subject-grid-221 {
grid-template-columns: 1fr;
gap: 16px;
}
.card-item-5 {
grid-column: auto;
max-width: 100%;
justify-self: stretch;
}
}
/* 라이트박스 모달 */
.modal-backdrop {
position: fixed;
inset: 0;
background: rgba(15, 23, 42, 0.75);
backdrop-filter: blur(6px);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
padding: 16px;
}
.modal-card {
position: relative;
background: #ffffff;
border-radius: 24px;
max-width: 900px;
width: 100%;
max-height: 90vh;
overflow-y: auto;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
border: 1px solid rgba(255, 255, 255, 0.2);
}
.modal-close-btn {
position: absolute;
top: 16px;
right: 16px;
width: 36px;
height: 36px;
border-radius: 50%;
background: #f1f5f9;
border: none;
font-size: 1.1rem;
color: #475569;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
z-index: 20;
transition: all 0.2s ease;
}
.modal-close-btn:hover {
background: #e2e8f0;
color: #0f172a;
}
.modal-grid {
display: grid;
grid-template-columns: 1fr;
}
@media (min-width: 768px) {
.modal-grid {
grid-template-columns: 1fr 1.15fr;
}
}
.modal-img-col {
position: relative;
background: #0f172a;
display: flex;
align-items: center;
justify-content: center;
min-height: 300px;
}
.modal-main-img {
width: 100%;
height: 100%;
max-height: 520px;
object-fit: cover;
display: block;
}
.modal-img-badge {
position: absolute;
top: 16px;
left: 16px;
background: var(--accent-color, #d97706);
color: #ffffff;
font-size: 0.75rem;
font-weight: 800;
padding: 5px 12px;
border-radius: 9999px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
.modal-content-col {
padding: clamp(24px, 4vw, 36px);
display: flex;
flex-direction: column;
justify-content: space-between;
}
.modal-pill {
display: inline-block;
font-size: 0.75rem;
font-weight: 700;
color: var(--primary-color, #1e3a8a);
background: rgba(30, 58, 138, 0.08);
padding: 4px 10px;
border-radius: 9999px;
margin-bottom: 8px;
}
.modal-title {
font-size: clamp(1.4rem, 3vw, 1.85rem);
font-weight: 900;
color: #0f172a;
letter-spacing: -0.5px;
line-height: 1.25;
}
.modal-title .text-sub {
display: block;
font-size: 1rem;
font-weight: 700;
color: var(--primary-color, #1e3a8a);
margin-top: 4px;
}
.modal-slogan {
font-size: 0.88rem;
color: #475569;
margin-top: 8px;
line-height: 1.5;
word-break: keep-all;
}
.modal-points {
margin: 20px 0;
display: flex;
flex-direction: column;
gap: 12px;
background: #f8fafc;
padding: 16px;
border-radius: 16px;
border: 1px solid #e2e8f0;
}
.point-row {
display: flex;
gap: 12px;
align-items: flex-start;
}
.point-num {
font-size: 0.85rem;
font-weight: 900;
color: var(--primary-color, #1e3a8a);
background: #ffffff;
padding: 2px 8px;
border-radius: 6px;
border: 1px solid #cbd5e1;
flex-shrink: 0;
}
.point-head {
display: block;
font-size: 0.88rem;
font-weight: 800;
color: #1e293b;
margin-bottom: 2px;
}
.point-body {
font-size: 0.78rem;
color: #64748b;
line-height: 1.45;
word-break: keep-all;
}
.modal-actions {
display: flex;
gap: 10px;
flex-wrap: wrap;
margin-top: 10px;
}
.btn-modal-apply {
flex: 1 1 200px;
background: var(--primary-color, #1e3a8a);
color: #ffffff;
font-size: 0.92rem;
font-weight: 800;
padding: 14px 20px;
border-radius: 14px;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 14px rgba(30, 58, 138, 0.25);
transition: all 0.2s ease;
}
.btn-modal-apply:hover {
filter: brightness(1.1);
transform: translateY(-2px);
}
.btn-modal-link {
background: #f1f5f9;
color: #334155;
font-size: 0.85rem;
font-weight: 700;
padding: 14px 18px;
border-radius: 14px;
border: 1px solid #cbd5e1;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
}
.btn-modal-link:hover {
background: #e2e8f0;
color: #0f172a;
}
/* 모달 트랜지션 */
.modal-fade-enter-active,
.modal-fade-leave-active {
transition: opacity 0.3s ease;
}
.modal-fade-enter-from,
.modal-fade-leave-to {
opacity: 0;
}
.modal-fade-enter-active .modal-card,
.modal-fade-leave-active .modal-card {
transition: transform 0.3s cubic-bezier(0.25, 1, 0.5, 1);
}
.modal-fade-enter-from .modal-card,
.modal-fade-leave-to .modal-card {
transform: scale(0.92) translateY(20px);
}
</style>
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

+7
View File
@@ -62,6 +62,13 @@
:subjectName="parsed.subjectName" :subjectName="parsed.subjectName"
/> />
<!-- 12. 과목별 1타 강사진 갤러리 캐러셀 (클릭 시 페이지 모달 확대 및 상담 연동) -->
<SubjectCarousel
:regionDong="parsed.dong"
:grade="parsed.grade"
:currentSubject="parsed.subjectName"
/>
<!-- 웹 광고 단일 목적: 해당 학년과 과목이 기본 선택된 무료 상담 신청 폼 --> <!-- 웹 광고 단일 목적: 해당 학년과 과목이 기본 선택된 무료 상담 신청 폼 -->
<ConsultForm <ConsultForm
:regionName="parsed.shortRegionName" :regionName="parsed.shortRegionName"
+326 -235
View File
@@ -1,189 +1,261 @@
<template> <template>
<div class="landing-container bg-[#F0F9FF] text-slate-800 antialiased relative pb-24 md:pb-12 min-h-screen w-full"> <div class="landing-container bg-[#F8FAFC] text-slate-800 antialiased relative min-h-screen w-full">
<!-- Header --> <!-- 1. Header (클린 미니멀 프리미엄 네비게이션) -->
<header class="bg-white border-b border-slate-200 sticky top-0 z-40 shadow-sm w-full"> <header class="bg-white/95 backdrop-blur-md border-b border-slate-200/80 sticky top-0 z-40 w-full transition-all">
<div class="max-w-6xl mx-auto px-4 sm:px-6 py-3.5 flex items-center justify-between"> <div class="max-w-6xl mx-auto px-4 sm:px-6 py-3.5 flex items-center justify-between">
<div class="flex items-center space-x-2"> <div class="flex items-center gap-3">
<div class="w-9 h-9 rounded-xl bg-sky-600 flex items-center justify-center text-white font-extrabold text-lg shadow-sm"> <div class="w-9 h-9 rounded-xl bg-blue-600 flex items-center justify-center text-white font-extrabold text-base shadow-sm">
T T
</div> </div>
<div> <div class="flex items-center gap-2">
<span class="font-extrabold text-xl sm:text-2xl tracking-tight text-sky-950">{{ siteName }}</span> <span class="font-extrabold text-lg sm:text-xl tracking-tight text-slate-900">{{ siteName }}</span>
<span class="text-[10px] font-bold text-cyan-700 bg-cyan-50 px-2 py-0.5 rounded-full ml-1.5 border border-cyan-200">SMART 정밀 진단</span> <span class="hidden sm:inline-flex items-center text-[11px] font-semibold text-blue-700 bg-blue-50 px-2.5 py-0.5 rounded-full border border-blue-100">
교육청 등록 협력
</span>
</div> </div>
</div> </div>
<div class="flex items-center space-x-4"> <div class="flex items-center gap-4">
<a href="tel:010-5961-5807" class="hidden sm:flex items-center gap-1.5 text-sm font-semibold text-slate-600 hover:text-sky-600 transition"> <a href="tel:010-5961-5807" class="hidden sm:flex items-center gap-1.5 text-sm font-semibold text-slate-600 hover:text-blue-600 transition">
<i class="fa-solid fa-phone text-sky-600"></i> <i class="fa-solid fa-phone text-blue-600 text-xs"></i>
<span>010-5961-5807</span> <span>010-5961-5807</span>
</a> </a>
<a href="#leadFormSection" class="bg-sky-600 hover:bg-sky-700 text-white text-xs sm:text-sm font-bold px-5 py-2.5 rounded-full transition shadow-md flex items-center gap-1.5"> <a href="#leadFormSection" class="bg-blue-600 hover:bg-blue-700 text-white text-xs sm:text-sm font-bold px-4 sm:px-5 py-2.5 rounded-xl transition shadow-sm hover:shadow flex items-center gap-1.5">
<span>정밀 진단 신청</span> <span>무료 시범수업 신청</span>
<i class="fa-solid fa-arrow-right text-[11px]"></i> <i class="fa-solid fa-arrow-right text-[11px]"></i>
</a> </a>
</div> </div>
</div> </div>
</header> </header>
<!-- 메인 컨텐츠 (좌우 꽉 찬 와이드) --> <!-- 2. Main Body -->
<main class="w-full bg-[#F0F9FF] min-h-screen pb-20"> <main class="w-full pb-20">
<!-- 히어로 섹션 (테크 블루 & 사이언 풀와이드) --> <!-- 히어로 섹션 (AI 스타일 형광/물결 제거, 정제된 모던 에듀테크 캔버스) -->
<section class="w-full bg-gradient-to-b from-[#0369A1] via-[#0275B2] to-[#0284C7] text-white px-4 sm:px-6 pt-12 pb-20 rounded-b-[2.5rem] relative overflow-hidden text-center shadow-lg"> <section class="w-full bg-white border-b border-slate-200/80 pt-12 sm:pt-16 pb-20 px-4 sm:px-6 text-center relative overflow-hidden">
<div class="absolute -right-24 -top-24 w-96 h-96 bg-cyan-400/20 rounded-full blur-3xl pointer-events-none"></div>
<div class="absolute -left-24 bottom-0 w-96 h-96 bg-sky-300/20 rounded-full blur-3xl pointer-events-none"></div> <!-- 은은한 상단 엠비언트 라이트 (절제된 디자이너 톤) -->
<div class="absolute inset-0 bg-gradient-to-b from-blue-50/40 via-transparent to-transparent pointer-events-none"></div>
<div class="max-w-4xl mx-auto relative z-10"> <div class="max-w-4xl mx-auto relative z-10">
<div class="inline-flex items-center gap-2 bg-white/10 backdrop-blur-md border border-white/20 px-4 py-1.5 rounded-full text-xs sm:text-sm font-medium text-sky-100 mb-5 shadow-sm">
<span class="w-2.5 h-2.5 rounded-full bg-cyan-300 animate-ping"></span> <!-- 신뢰 인증 뱃지 -->
<span>관내 초·중·고 학교별 내신 기출 완벽 분석</span> <div class="inline-flex items-center gap-2 px-3.5 py-1.5 rounded-full text-xs font-semibold bg-slate-50 border border-slate-200 text-slate-700 shadow-xs mb-6">
<span class="w-2 h-2 rounded-full bg-blue-600"></span>
<span>인천 전지역 전담 | 명문대 및 베테랑 전문 강사진 100% 신원 보증</span>
</div> </div>
<h1 class="text-2xl sm:text-4xl md:text-5xl font-extrabold leading-snug sm:leading-tight tracking-tight text-white mb-4"> <!-- 메인 H1 (검색 상위 노출 30자 규격 및 학부모 고의도 롱테일 키워드) -->
우리 동네 학교별 맞춤 내신·수능 대비<br class="hidden sm:inline"> <h1 class="text-3xl sm:text-4xl md:text-5xl font-extrabold tracking-tight text-slate-900 leading-[1.2] sm:leading-[1.18] mb-4">
<span class="text-cyan-200 underline decoration-wavy decoration-cyan-300">취약 단원 핀포인트 1:1 클리닉</span> 무료 리포트 신청 인천 초·중·고 1:1 맞춤 과외 매칭<br class="hidden sm:inline" />
<span class="text-blue-600">검증된 전문 선생님 100% 매칭</span>
</h1> </h1>
<p class="text-xs sm:text-base text-sky-100/90 font-normal max-w-2xl mx-auto leading-relaxed mb-8"> <!-- 서브 헤드라인 (비용 시세 비교 + 무료 시범수업 신뢰 트리거) -->
어디서 틀리는지 모르는 막연한 공부는 끝! 취약 개념을 역추적하여 가장 빠른 성적 향상 지름길을 찾아드립니다. <p class="text-sm sm:text-base text-slate-600 font-normal max-w-2xl mx-auto leading-relaxed mb-8">
과외 비용·시세 투명 비교부터 무료 시범수업 신청까지.<br class="hidden sm:inline" />
인천 관내 학교별 기출 족보를 완벽 분석하여 <strong>내신 1등급 역전 솔루션</strong>을 제공합니다.
</p> </p>
<!-- 지표 카운터 --> <!-- 4대 핵심 신뢰 보증 지표 (Trust Bar) -->
<div class="grid grid-cols-3 gap-3 bg-white/10 backdrop-blur-md border border-white/20 rounded-2xl p-4 sm:p-5 text-center max-w-xl mx-auto mb-6 shadow-inner"> <div class="grid grid-cols-2 md:grid-cols-4 gap-2.5 sm:gap-3 max-w-3xl mx-auto mb-8">
<div class="bg-slate-50 border border-slate-200/90 rounded-xl p-3 text-left flex items-start gap-2.5">
<i class="fa-solid fa-circle-check text-blue-600 text-base mt-0.5 shrink-0"></i>
<div> <div>
<div class="text-[11px] sm:text-xs text-sky-200">지역 전담 강사진</div> <strong class="block text-xs sm:text-sm font-bold text-slate-900">100% 서류 검증</strong>
<div class="font-extrabold text-base sm:text-2xl text-white mt-0.5">3,500<span class="text-xs sm:text-sm font-normal">+명</span></div> <span class="text-[11px] text-slate-500 leading-tight">학력·경력·신원 전수 인증</span>
</div>
<div class="border-x border-white/20">
<div class="text-[11px] sm:text-xs text-sky-200">학교별 기출 분석</div>
<div class="font-extrabold text-base sm:text-2xl text-cyan-200 mt-0.5">100<span class="text-xs sm:text-sm font-normal">%</span></div>
</div>
<div>
<div class="text-[11px] sm:text-xs text-sky-200">성적 향상 만족도</div>
<div class="font-extrabold text-base sm:text-2xl text-white mt-0.5">98.9<span class="text-xs sm:text-sm font-normal">%</span></div>
</div> </div>
</div> </div>
<!-- 실시간 롤링 알림 --> <div class="bg-slate-50 border border-slate-200/90 rounded-xl p-3 text-left flex items-start gap-2.5">
<div class="bg-black/30 backdrop-blur-md rounded-full px-4 py-2 flex items-center justify-center gap-2.5 text-xs text-slate-200 border border-white/15 mx-auto max-w-md shadow-md"> <i class="fa-solid fa-circle-check text-blue-600 text-base mt-0.5 shrink-0"></i>
<span class="bg-sky-500 text-white text-[10px] font-bold px-2 py-0.5 rounded-full">실시간</span> <div>
<span class="truncate font-medium transition-opacity duration-300">{{ currentNotice }}</span> <strong class="block text-xs sm:text-sm font-bold text-slate-900">무료 시범수업</strong>
<span class="text-[11px] text-slate-500 leading-tight">직접 수업받아보고 결정</span>
</div> </div>
</div> </div>
<div class="bg-slate-50 border border-slate-200/90 rounded-xl p-3 text-left flex items-start gap-2.5">
<i class="fa-solid fa-circle-check text-blue-600 text-base mt-0.5 shrink-0"></i>
<div>
<strong class="block text-xs sm:text-sm font-bold text-slate-900">과외 비용 시세 비교</strong>
<span class="text-[11px] text-slate-500 leading-tight">동네별 거품 없는 투명 시세</span>
</div>
</div>
<div class="bg-slate-50 border border-slate-200/90 rounded-xl p-3 text-left flex items-start gap-2.5">
<i class="fa-solid fa-circle-check text-blue-600 text-base mt-0.5 shrink-0"></i>
<div>
<strong class="block text-xs sm:text-sm font-bold text-slate-900">학교별 기출 분석</strong>
<span class="text-[11px] text-slate-500 leading-tight">인천 관내 중·고교 족보</span>
</div>
</div>
</div>
<!-- 실시간 매칭 알림 롤링 바 (세련된 미니멀 디자인) -->
<div class="inline-flex items-center gap-2.5 bg-slate-100/90 border border-slate-200/80 rounded-full px-4 py-1.5 text-xs text-slate-600 shadow-xs">
<span class="w-1.5 h-1.5 rounded-full bg-emerald-500"></span>
<span class="font-bold text-slate-700">실시간 접수</span>
<span class="text-slate-300">|</span>
<span class="truncate max-w-[260px] sm:max-w-md font-medium text-slate-600">{{ currentNotice }}</span>
</div>
</div>
</section> </section>
<!-- 리드 수집 폼 섹션 (상단 카드 오버랩) --> <!-- 3. 리드 수집 폼 섹션 (상급자 에듀테크 플랫폼 스타일 모듈) -->
<section id="leadFormSection" class="px-4 sm:px-6 -mt-10 relative z-20 max-w-3xl mx-auto"> <section id="leadFormSection" class="px-4 sm:px-6 -mt-10 relative z-20 max-w-3xl mx-auto">
<div class="bg-white rounded-3xl shadow-2xl border border-slate-200/80 p-6 sm:p-8 transition-all"> <div class="bg-white rounded-2xl shadow-xl border border-slate-200/90 p-6 sm:p-9 transition-all">
<header class="text-center mb-6 pb-4 border-b border-slate-100"> <header class="text-center mb-7 pb-5 border-b border-slate-100">
<span class="inline-block px-3 py-1 rounded-full text-xs font-bold bg-sky-100 text-sky-800 mb-2"> <div class="inline-block px-3 py-1 rounded-full text-xs font-bold bg-blue-50 text-blue-700 border border-blue-100 mb-2">
선착순 30명 정밀 분석 무료 선착순 30명 한정 전액 무료
</span> </div>
<h2 class="text-xl sm:text-2xl font-bold text-slate-900"> <h2 class="text-xl sm:text-2xl font-extrabold text-slate-900 tracking-tight">
분석받고 싶은 과목과 학년을 선택하세요! 우리 동네 과외 시세 확인 & 무료 시범수업 신청
</h2> </h2>
<p class="text-xs sm:text-sm text-slate-500 mt-1"> <p class="text-xs sm:text-sm text-slate-500 mt-1">
오답 패턴을 정밀 진단하여 최적의 단원 보완 플랜과 전문 선생님을 매칭합니다. 단 1분 간단 입력으로 아이에게 가장 적합한 1:1 맞춤 선생님과 진단 리포트를 배정해 드립니다.
</p> </p>
</header> </header>
<form @submit.prevent="handleSubmit" class="space-y-5"> <form @submit.prevent="handleSubmit" class="space-y-6">
<!-- 학년 & 취약 과목 --> <!-- 1) 학년 선택 (초등 / 중등 / 고등 분기 탭 & 세부 선택) -->
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div> <div>
<label for="studentGrade" class="block text-xs sm:text-sm font-bold text-slate-700 mb-1.5"> <label for="studentGrade" class="block text-xs sm:text-sm font-bold text-slate-800 mb-2">
학년 선택 <span class="text-sky-600">*</span> 1. 학생 학년 선택 <span class="text-blue-600">*</span>
</label> </label>
<select id="studentGrade" v-model="formData.grade" required class="w-full bg-slate-50 border border-slate-300 text-slate-800 text-xs sm:text-sm rounded-xl focus:ring-2 focus:ring-sky-600 focus:border-sky-600 p-3 outline-none font-medium transition"> <div class="grid grid-cols-1 sm:grid-cols-3 gap-2 mb-2">
<option value="" disabled>학년 선택</option> <button
<optgroup label="중등부 (내신·기출 분석)"> type="button"
<option value="중학교 1학년">중학교 1학년 (기초개념 데이터)</option> @click="selectGradeStage('초등')"
<option value="중학교 2학년">중학교 2학년 (내신 킬러문항)</option> :class="[
<option value="중학교 3학년">중학교 3학년 (고등선행 심화)</option> 'py-2.5 px-3 rounded-xl text-xs sm:text-sm font-bold transition border',
</optgroup> gradeStage === '초등'
<optgroup label="고등부 (내신·수능 클리닉)"> ? 'bg-blue-50 border-blue-600 text-blue-700 shadow-xs'
<option value="고등학교 1학년">고등학교 1학년 (공통수학/영어)</option> : 'bg-white border-slate-200 text-slate-700 hover:bg-slate-50'
<option value="고등학교 2학년">고등학교 2학년 (선택과목 심화)</option> ]"
<option value="고등학교 3학년/N수">고등학교 3학년 / N수 (수능 실전)</option> >
</optgroup> 초등부 (1~6학년)
<optgroup label="초등부"> </button>
<option value="초등 5~6학년">초등 5~6학년 (중등 브릿지)</option> <button
</optgroup> type="button"
@click="selectGradeStage('중등')"
:class="[
'py-2.5 px-3 rounded-xl text-xs sm:text-sm font-bold transition border',
gradeStage === '중등'
? 'bg-blue-50 border-blue-600 text-blue-700 shadow-xs'
: 'bg-white border-slate-200 text-slate-700 hover:bg-slate-50'
]"
>
중등부 (1~3학년)
</button>
<button
type="button"
@click="selectGradeStage('고등')"
:class="[
'py-2.5 px-3 rounded-xl text-xs sm:text-sm font-bold transition border',
gradeStage === '고등'
? 'bg-blue-50 border-blue-600 text-blue-700 shadow-xs'
: 'bg-white border-slate-200 text-slate-700 hover:bg-slate-50'
]"
>
고등부 / N수
</button>
</div>
<select
id="studentGrade"
v-model="formData.grade"
required
class="w-full bg-slate-50 border border-slate-200 text-slate-800 text-xs sm:text-sm rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-blue-500 p-3 outline-none font-medium transition"
>
<option value="" disabled>세부 학년을 선택해 주세요</option>
<option v-for="opt in currentGradeOptions" :key="opt" :value="opt">{{ opt }}</option>
</select> </select>
</div> </div>
<!-- 2) 취약 과목 빠른 선택 (Chip 버튼) -->
<div> <div>
<label for="weakSubject" class="block text-xs sm:text-sm font-bold text-slate-700 mb-1.5"> <div class="flex justify-between items-center mb-2">
취약 과목 <span class="text-sky-600">*</span> <label class="block text-xs sm:text-sm font-bold text-slate-800">
2. 집중 지도가 필요한 과목 <span class="text-blue-600">*</span>
</label> </label>
<select id="weakSubject" v-model="formData.subject" required class="w-full bg-slate-50 border border-slate-300 text-slate-800 text-xs sm:text-sm rounded-xl focus:ring-2 focus:ring-sky-600 focus:border-sky-600 p-3 outline-none font-medium transition"> <span class="text-[11px] text-slate-400 font-normal">복수/단일 클릭</span>
<option value="" disabled>과목 선택</option>
<option value="수학">수학 (개념 역추적 & 킬러 문항)</option>
<option value="영어">영어 (구문 독해 & 빈칸 추론)</option>
<option value="과학">과학 (물리·화학·생명·지구과학)</option>
<option value="국어">국어 (비문학 제재별 독해 분석)</option>
<option value="사회/역사">사회/역사 (도표·사료 분석)</option>
</select>
</div> </div>
</div> <div class="grid grid-cols-3 sm:grid-cols-6 gap-2 text-center">
<!-- 빠른 과목 픽 -->
<div>
<div class="text-xs font-semibold text-slate-500 mb-2 flex justify-between items-center">
<span>빠른 과목 픽 (PICK)</span>
<span class="text-xs text-sky-600 font-semibold">터치 시 자동 선택</span>
</div>
<div class="grid grid-cols-5 gap-2 text-center">
<button <button
v-for="subj in subjects" v-for="subj in subjects"
:key="subj.name" :key="subj.name"
type="button" type="button"
@click="formData.subject = subj.name" @click="formData.subject = subj.name"
:class="[ :class="[
'py-2 px-1 rounded-xl text-xs sm:text-sm font-bold transition shadow-sm', 'py-2.5 px-2 rounded-xl text-xs sm:text-sm font-bold transition border',
formData.subject === subj.name formData.subject === subj.name
? 'border-2 border-sky-600 bg-sky-50 text-sky-800 ring-2 ring-sky-300/50' ? 'bg-blue-600 border-blue-600 text-white shadow-sm'
: 'border border-slate-200 text-slate-700 hover:border-sky-400 bg-white' : 'bg-white border-slate-200 text-slate-700 hover:bg-slate-50'
]" ]"
> >
<span>{{ subj.label }}</span> <span>{{ subj.label }}</span>
<span class="block text-[10px] font-normal" :class="formData.subject === subj.name ? 'text-sky-700 font-semibold' : 'text-slate-400'"> <span class="block text-[10px] font-normal" :class="formData.subject === subj.name ? 'text-blue-100' : 'text-slate-400'">
{{ subj.badge }} {{ subj.badge }}
</span> </span>
</button> </button>
</div> </div>
</div> </div>
<!-- 공부 고민 체크박스 --> <!-- 3) 희망 수업 형태 (방문 / 화상) -->
<div> <div>
<label class="block text-xs sm:text-sm font-bold text-slate-700 mb-2"> <label class="block text-xs sm:text-sm font-bold text-slate-800 mb-2">
현재 가장 큰 고민은 무엇인가요? (복수 선택 가능) 3. 희망 수업 형태
</label> </label>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2.5 text-xs sm:text-sm"> <div class="grid grid-cols-3 gap-2">
<label v-for="c in concernOptions" :key="c" class="flex items-center gap-2.5 p-3 bg-slate-50 border border-slate-200 rounded-xl cursor-pointer hover:bg-sky-50/50 transition"> <label
<input type="checkbox" :value="c" v-model="formData.concerns" class="w-4 h-4 text-sky-600 rounded border-slate-300 focus:ring-sky-500"> v-for="type in lessonTypes"
:key="type"
class="flex items-center justify-center p-3 rounded-xl border text-xs sm:text-sm font-semibold cursor-pointer transition text-center"
:class="formData.lessonType === type ? 'bg-blue-50 border-blue-600 text-blue-700 font-bold' : 'bg-white border-slate-200 text-slate-700 hover:bg-slate-50'"
>
<input type="radio" :value="type" v-model="formData.lessonType" class="hidden" />
<span>{{ type }}</span>
</label>
</div>
</div>
<!-- 4) 현재 가장 큰 고민 (체크박스) -->
<div>
<label class="block text-xs sm:text-sm font-bold text-slate-800 mb-2">
4. 현재 가장 큰 학습 고민 (복수 선택 가능)
</label>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2 text-xs sm:text-sm">
<label v-for="c in concernOptions" :key="c" class="flex items-center gap-2.5 p-3 bg-slate-50 border border-slate-200/90 rounded-xl cursor-pointer hover:bg-slate-100/70 transition">
<input type="checkbox" :value="c" v-model="formData.concerns" class="w-4 h-4 text-blue-600 rounded border-slate-300 focus:ring-blue-500">
<span class="text-slate-700 text-xs sm:text-sm font-medium">{{ c }}</span> <span class="text-slate-700 text-xs sm:text-sm font-medium">{{ c }}</span>
</label> </label>
</div> </div>
</div> </div>
<!-- 거주 지역 / 학교 --> <!-- 5) 거주 지역 / 학교명 입력 -->
<div> <div>
<label for="regionInput" class="block text-xs sm:text-sm font-bold text-slate-700 mb-1.5"> <label for="regionInput" class="block text-xs sm:text-sm font-bold text-slate-800 mb-1.5">
거주 지역 및 학교명 <span class="text-slate-400 font-normal text-xs">(지역 내신 기출 DB 매칭)</span> 5. 거주 지역 및 재학 학교명 <span class="text-slate-400 font-normal text-xs">(인근 학교 기출 족보 매칭용)</span>
</label> </label>
<input type="text" id="regionInput" v-model="formData.region" placeholder="예: 경기 성남시 분당구 수내동 / 수내고" class="w-full bg-slate-50 border border-slate-300 text-slate-800 text-xs sm:text-sm rounded-xl focus:ring-2 focus:ring-sky-600 focus:border-sky-600 p-3 outline-none placeholder:text-slate-400 transition"> <input
type="text"
id="regionInput"
v-model="formData.region"
placeholder="예: 인천 연수구 송도동 / 송도고"
class="w-full bg-slate-50 border border-slate-200 text-slate-800 text-xs sm:text-sm rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-blue-500 p-3.5 outline-none placeholder:text-slate-400 transition"
/>
</div> </div>
<!-- 학부모 연락처 --> <!-- 6) 학부모 연락처 -->
<div> <div>
<label for="parentPhone" class="block text-xs sm:text-sm font-bold text-slate-700 mb-1.5"> <label for="parentPhone" class="block text-xs sm:text-sm font-bold text-slate-800 mb-1.5">
학부모 연락처 <span class="text-sky-600">*</span> 6. 학부모 연락처 <span class="text-blue-600">*</span>
<span class="text-slate-400 font-normal text-xs">(정밀 진단표 발송용)</span> <span class="text-slate-400 font-normal text-xs">(과외 시세 안내 및 시범수업 조율용)</span>
</label> </label>
<div class="relative"> <div class="relative">
<input <input
@@ -194,152 +266,151 @@
required required
placeholder="010-0000-0000" placeholder="010-0000-0000"
maxlength="13" maxlength="13"
class="w-full bg-slate-50 border border-slate-300 text-slate-900 text-base font-semibold rounded-xl focus:ring-2 focus:ring-sky-600 focus:border-sky-600 p-3.5 pl-11 outline-none tracking-wider" class="w-full bg-slate-50 border border-slate-200 text-slate-900 text-base font-bold rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-blue-500 p-3.5 pl-11 outline-none tracking-wider"
> />
<i class="fa-solid fa-mobile-screen-button absolute left-4 top-4 text-slate-400 text-base"></i> <i class="fa-solid fa-mobile-screen absolute left-4 top-4 text-slate-400 text-base"></i>
</div> </div>
</div> </div>
<!-- 개인정보 동의 --> <!-- 개인정보 동의 -->
<div class="flex items-center gap-2 text-xs text-slate-500 pt-1"> <div class="flex items-center gap-2 text-xs text-slate-500 pt-1">
<input type="checkbox" id="privacyAgree" v-model="formData.privacy" required class="w-4 h-4 text-sky-600 rounded border-slate-300 focus:ring-sky-500"> <input type="checkbox" id="privacyAgree" v-model="formData.privacy" required class="w-4 h-4 text-blue-600 rounded border-slate-300 focus:ring-blue-500">
<label for="privacyAgree" class="cursor-pointer"> <label for="privacyAgree" class="cursor-pointer">
[필수] 개인정보 수집 및 상담 안내 제공에 동의합니다. [필수] 과외 상담 및 무료 시범수업 안내를 위한 개인정보 수집에 동의합니다.
</label> </label>
</div> </div>
<!-- 제출 버튼 --> <!-- 제출 버튼 (고급스러운 솔리드 로열 블루) -->
<button <button
type="submit" type="submit"
:disabled="isSubmitting" :disabled="isSubmitting"
class="w-full bg-gradient-to-r from-sky-600 via-cyan-600 to-sky-600 hover:opacity-95 text-white font-extrabold text-base sm:text-lg py-4 px-6 rounded-2xl shadow-xl transition flex items-center justify-center gap-2 disabled:opacity-50" class="w-full bg-blue-600 hover:bg-blue-700 text-white font-extrabold text-base sm:text-lg py-4 px-6 rounded-xl shadow-md hover:shadow-lg transition-all flex items-center justify-center gap-2 disabled:opacity-50"
> >
<i class="fa-solid fa-chart-column text-lg"></i> <i class="fa-solid fa-circle-check text-lg"></i>
<span>{{ isSubmitting ? '분석 중...' : '정밀 진단 리포트 & 1:1 클리닉 신청하기' }}</span> <span>{{ isSubmitting ? '신청서 접수 중...' : '우리 동네 과외 시세 확인 & 무료 시범수업 신청하기' }}</span>
</button> </button>
<div class="text-center text-xs text-slate-400 flex items-center justify-center gap-1.5"> <div class="text-center text-xs text-slate-400 flex items-center justify-center gap-1.5">
<i class="fa-solid fa-lock text-xs"></i> <i class="fa-solid fa-shield-halved text-xs"></i>
<span>입력하신 정보는 상담 및 리포트 제공 목적으로만 안전하게 보관됩니다.</span> <span>입력하신 개인정보는 암호화되어 안전하게 보호되며, 무분별한 광고 전화를 드리지 않습니다.</span>
</div> </div>
<!-- 안내 문구 (상담 결과 전달 시 원활 진행 안내) --> <!-- 안내 박스 -->
<div class="mt-3 p-3.5 bg-sky-50/90 border border-sky-200/90 rounded-xl flex items-start gap-2.5 text-xs text-sky-950 leading-relaxed shadow-sm"> <div class="mt-3 p-3.5 bg-blue-50/60 border border-blue-100 rounded-xl flex items-start gap-2.5 text-xs text-slate-700 leading-relaxed">
<i class="fa-solid fa-circle-info text-sky-600 mt-0.5 text-sm shrink-0"></i> <i class="fa-solid fa-circle-info text-blue-600 mt-0.5 text-sm shrink-0"></i>
<div> <div>
<strong class="font-bold text-sky-950 block mb-0.5">원활한 상담 진행 안내</strong> <strong class="font-bold text-slate-900 block mb-0.5">신속 상담 안내</strong>
<span>상담 신청 후 안내받으신 <strong>상담결과를 매니저에게 전달해 주시면</strong> 더욱 원활하고 신속한 맞춤 강사 배정과 심층 상담이 진행됩니다. (직통 문의: <a href="tel:010-5961-5807" class="font-extrabold text-sky-900 underline hover:text-sky-700">010-5961-5807</a>)</span> <span>접수 즉시 인천 지역 전담 매니저가 학교별 출제 경향과 최적의 선생님 매칭 일정을 유선으로 안내해 드립니다. (직통 상담: <a href="tel:010-5961-5807" class="font-bold text-blue-600 underline">010-5961-5807</a>)</span>
</div> </div>
</div> </div>
</form> </form>
<!-- 완료 메시지 --> <!-- 완료 메시지 -->
<div v-if="submitSuccess" id="submitResultBox" class="mt-5 p-5 bg-emerald-50 border border-emerald-300 rounded-2xl text-emerald-900 text-xs sm:text-sm"> <div v-if="submitSuccess" id="submitResultBox" class="mt-5 p-5 bg-emerald-50 border border-emerald-300 rounded-xl text-emerald-950 text-xs sm:text-sm">
<div class="flex items-center gap-2 font-bold text-sm sm:text-base mb-1.5 text-emerald-800"> <div class="flex items-center gap-2 font-bold text-sm sm:text-base mb-1.5 text-emerald-800">
<i class="fa-solid fa-circle-check text-emerald-600 text-lg"></i> <i class="fa-solid fa-circle-check text-emerald-600 text-lg"></i>
<span>학습 정밀 진단 신청이 성공적으로 접수되었습니다!</span> <span>맞춤 과외 시세 및 무료 시범수업 신청이 완료되었습니다!</span>
</div> </div>
<p class="leading-relaxed"> <p class="leading-relaxed text-slate-700">
기재해주신 연락처로 <strong>‘취약 단원 정밀 분석 리포트’</strong>가 발송되며, 전문 입시 분석관이 유선으로 심층 솔루션을 안내해 드립니다. 기재해주신 연락처로 <strong>‘인천 관내 학교별 내신 분석 요약표’</strong>가 발송되며, 전문 학습 매니저가 1:1 맞춤 선생님 추천 및 무료 모의수업 일정을 조율해 드립니다.
</p> </p>
<div class="mt-3 p-2.5 bg-white/80 rounded-xl border border-emerald-200 text-xs text-emerald-900 flex items-start gap-2">
<i class="fa-solid fa-lightbulb text-emerald-600 mt-0.5 shrink-0"></i>
<span><strong>안내:</strong> 매니저 유선 상담 시 <strong>상담결과를 공유해 주시면</strong> 수준별 맞춤 커리큘럼 설계가 훨씬 원활하게 진행됩니다. (문의: 010-5961-5807)</span>
</div>
</div> </div>
</div> </div>
</section> </section>
<!-- 4. 성적 향상 사례 (깔끔하고 신뢰도 높은 후기 그리드) -->
<!-- 성적 향상 사례 (데스크톱 와이드 2열) -->
<section class="mt-16 px-4 sm:px-6 max-w-6xl mx-auto"> <section class="mt-16 px-4 sm:px-6 max-w-6xl mx-auto">
<header class="text-center mb-8"> <header class="text-center mb-8">
<span class="text-xs sm:text-sm font-bold text-sky-700 tracking-wider bg-sky-100 px-3 py-1 rounded-full">DATA-DRIVEN SUCCESS</span> <span class="text-xs sm:text-sm font-bold text-blue-600 tracking-wider bg-blue-50 px-3 py-1 rounded-full border border-blue-100">
<h2 class="text-2xl sm:text-3xl font-extrabold text-slate-900 mt-2">실제 성적 반등 결과</h2> PROVEN RESULTS
<p class="text-xs sm:text-sm text-slate-500 mt-1">데이터 분석으로 원인을 찾아 성적을 역전시킨 학생들의 사례입니다.</p> </span>
<h2 class="text-2xl sm:text-3xl font-extrabold text-slate-900 mt-2 tracking-tight">실제 성적 상승 및 수강 후기</h2>
<p class="text-xs sm:text-sm text-slate-500 mt-1">1:1 밀착 관리를 통해 내신 1등급과 수능 역전을 이뤄낸 학생들의 변화입니다.</p>
</header> </header>
<div class="grid grid-cols-1 md:grid-cols-2 gap-5 mb-6"> <div class="grid grid-cols-1 md:grid-cols-2 gap-5 mb-6">
<!-- Case 1 --> <!-- Case 1 -->
<div class="bg-white p-6 rounded-3xl border border-slate-200 shadow-sm hover:shadow-md transition"> <div class="bg-white p-6 rounded-2xl border border-slate-200/90 shadow-xs hover:shadow-md transition">
<div class="flex items-center justify-between mb-3"> <div class="flex items-center justify-between mb-3">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<span class="bg-sky-100 text-sky-800 font-bold text-xs px-2.5 py-1 rounded-full">공통수학 1등급</span> <span class="bg-blue-50 text-blue-700 font-bold text-xs px-2.5 py-1 rounded-md border border-blue-100">수학 역전</span>
<span class="font-bold text-sm sm:text-base text-slate-800">분당 수내동 고1 정OO 학생</span> <span class="font-bold text-sm sm:text-base text-slate-800">송도동 고2 정OO 학생</span>
</div> </div>
<span class="text-xs text-slate-400">3개월 만에 달성</span> <span class="text-xs text-slate-400 font-medium">3개월 만에 달성</span>
</div> </div>
<div> <div>
<div class="flex justify-between text-xs sm:text-sm mb-1.5 font-semibold"> <div class="flex justify-between text-xs sm:text-sm mb-1.5 font-semibold">
<span class="text-slate-400">진단 전: 4등급 (52점)</span> <span class="text-slate-400">진단 전: 5등급 (46점)</span>
<span class="text-sky-700 font-bold">진단 후: 1등급 (96점)</span> <span class="text-blue-600 font-bold">진단 후: 2등급 (91점)</span>
</div> </div>
<div class="w-full bg-slate-100 rounded-full h-3 overflow-hidden"> <div class="w-full bg-slate-100 rounded-full h-2.5 overflow-hidden">
<div class="bg-gradient-to-r from-slate-300 to-sky-600 h-3 rounded-full" style="width: 92%"></div> <div class="bg-blue-600 h-2.5 rounded-full" style="width: 85%"></div>
</div> </div>
</div> </div>
<p class="text-xs sm:text-sm text-slate-600 mt-3.5 bg-slate-50 p-3.5 rounded-xl leading-relaxed"> <p class="text-xs sm:text-sm text-slate-600 mt-3.5 bg-slate-50 p-3.5 rounded-xl leading-relaxed">
"어디서 틀리는지 모른 채 무작정 문제집만 풀었는데, 정밀 분석 리포트로 이차함수 판별식 연계 개념이 비어있다는 걸 알고 단기간에 메꿨습니다." "서술형 풀이 과정에서 감점되던 나쁜 습관을 1:1로 정확히 첨삭받고 이번 중간고사에서 1등급권으로 올라섰습니다."
</p> </p>
</div> </div>
<!-- Case 2 --> <!-- Case 2 -->
<div class="bg-white p-6 rounded-3xl border border-slate-200 shadow-sm hover:shadow-md transition"> <div class="bg-white p-6 rounded-2xl border border-slate-200/90 shadow-xs hover:shadow-md transition">
<div class="flex items-center justify-between mb-3"> <div class="flex items-center justify-between mb-3">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<span class="bg-cyan-100 text-cyan-800 font-bold text-xs px-2.5 py-1 rounded-full">과학 탐구 만점</span> <span class="bg-emerald-50 text-emerald-700 font-bold text-xs px-2.5 py-1 rounded-md border border-emerald-100">영어 서술형</span>
<span class="font-bold text-sm sm:text-base text-slate-800">판교 중3 윤OO 학생</span> <span class="font-bold text-sm sm:text-base text-slate-800">부평동 중3 강OO 학생</span>
</div> </div>
<span class="text-xs text-slate-400">2개월 만에 달성</span> <span class="text-xs text-slate-400 font-medium">2개월 만에 달성</span>
</div> </div>
<div> <div>
<div class="flex justify-between text-xs sm:text-sm mb-1.5 font-semibold"> <div class="flex justify-between text-xs sm:text-sm mb-1.5 font-semibold">
<span class="text-slate-400">진단 전: 62점 (C등급)</span> <span class="text-slate-400">진단 전: 71점 (B등급)</span>
<span class="text-cyan-700 font-bold">진단 후: 98점 (전교 2등)</span> <span class="text-emerald-600 font-bold">진단 후: 100점 (만점 1등)</span>
</div> </div>
<div class="w-full bg-slate-100 rounded-full h-3 overflow-hidden"> <div class="w-full bg-slate-100 rounded-full h-2.5 overflow-hidden">
<div class="bg-gradient-to-r from-slate-300 to-cyan-600 h-3 rounded-full" style="width: 96%"></div> <div class="bg-emerald-600 h-2.5 rounded-full" style="width: 98%"></div>
</div> </div>
</div> </div>
<p class="text-xs sm:text-sm text-slate-600 mt-3.5 bg-slate-50 p-3.5 rounded-xl leading-relaxed"> <p class="text-xs sm:text-sm text-slate-600 mt-3.5 bg-slate-50 p-3.5 rounded-xl leading-relaxed">
"물리 파트 공식 유도와 계산 실수 패턴을 정확히 잡아주셔서 내신 시험에서 만점에 가까운 점수를 받았습니다." "학교별 빈출 외부 지문과 변형 문항을 시험 전 3회 이상 훈련해 주셔서 실전에서 막힘없이 풀었습니다."
</p> </p>
</div> </div>
</div> </div>
<!-- 학부모 리뷰 (2열) --> <!-- 학부모 리뷰 (2열) -->
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4"> <div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div class="bg-white p-5 rounded-2xl border border-slate-200 shadow-sm text-left"> <div class="bg-white p-5 rounded-xl border border-slate-200/90 shadow-xs text-left">
<div class="text-amber-400 text-sm mb-2"> <div class="text-amber-400 text-xs mb-2">
<i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i> <i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i>
</div> </div>
<h4 class="font-bold text-sm sm:text-base text-slate-800">분당 파크뷰 학부모 이OO님</h4> <h4 class="font-bold text-sm sm:text-base text-slate-800">연수구 송도 학부모 이OO님</h4>
<p class="text-xs sm:text-sm text-slate-600 mt-1.5 leading-relaxed">"정밀 진단표가 학원 상담보다 훨씬 객관적이고 정확했습니다. 어디에 집중해야 할지 명확해졌어요."</p> <p class="text-xs sm:text-sm text-slate-600 mt-1.5 leading-relaxed">"학원에서는 진도만 나가서 늘 불안했는데, 과외 선생님께서 모르는 개념을 끝까지 잡고 가주시니 안심이 됩니다."</p>
</div> </div>
<div class="bg-white p-5 rounded-2xl border border-slate-200 shadow-sm text-left"> <div class="bg-white p-5 rounded-xl border border-slate-200/90 shadow-xs text-left">
<div class="text-amber-400 text-sm mb-2"> <div class="text-amber-400 text-xs mb-2">
<i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i> <i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i>
</div> </div>
<h4 class="font-bold text-sm sm:text-base text-slate-800">판교 백현마을 학부모 강OO님</h4> <h4 class="font-bold text-sm sm:text-base text-slate-800">남동구 구월동 학부모 김OO님</h4>
<p class="text-xs sm:text-sm text-slate-600 mt-1.5 leading-relaxed">"시간 낭비 없이 부족한 단원만 집중 공략하니 단 2개월 만에 성적이 수직 상승했습니다."</p> <p class="text-xs sm:text-sm text-slate-600 mt-1.5 leading-relaxed">"시범수업 때 아이 수준을 정확하게 짚어주셔서 신뢰가 생겼습니다. 비용도 거품 없이 합리적이라 추천합니다."</p>
</div> </div>
</div> </div>
</section> </section>
<!-- FAQ 섹션 --> <!-- 5. 과목별 1:1 맞춤과외 갤러리 캐러셀 (클릭 시 확대 모달 및 상담/이동) -->
<SubjectCarousel grade="초·중·고" />
<!-- 6. FAQ 섹션 (정돈된 아코디언) -->
<section class="mt-16 px-4 sm:px-6 max-w-4xl mx-auto"> <section class="mt-16 px-4 sm:px-6 max-w-4xl mx-auto">
<header class="text-center mb-8"> <header class="text-center mb-8">
<span class="text-xs sm:text-sm font-bold text-slate-400 tracking-wider">FAQ</span> <span class="text-xs sm:text-sm font-bold text-slate-400 tracking-wider">FAQ</span>
<h2 class="text-2xl sm:text-3xl font-extrabold text-slate-900 mt-1">자주 묻는 질문</h2> <h2 class="text-2xl sm:text-3xl font-extrabold text-slate-900 mt-1 tracking-tight">자주 묻는 질문</h2>
<p class="text-xs sm:text-sm text-slate-500 mt-1">궁금하신 내용을 미리 확인해 보세요.</p> <p class="text-xs sm:text-sm text-slate-500 mt-1">인천 학부모님들께서 가장 많이 문의하시는 과외 진행 절차입니다.</p>
</header> </header>
<div class="space-y-3"> <div class="space-y-3">
<div v-for="(faq, idx) in faqs" :key="idx" class="border border-slate-200 rounded-2xl overflow-hidden bg-white shadow-sm"> <div v-for="(faq, idx) in faqs" :key="idx" class="border border-slate-200 rounded-xl overflow-hidden bg-white shadow-xs">
<button @click="faq.open = !faq.open" class="w-full p-4 sm:p-5 text-left text-sm sm:text-base font-bold text-slate-800 flex justify-between items-center hover:bg-slate-50 transition"> <button @click="faq.open = !faq.open" class="w-full p-4 sm:p-5 text-left text-sm sm:text-base font-bold text-slate-800 flex justify-between items-center hover:bg-slate-50 transition">
<span>{{ faq.q }}</span> <span>{{ faq.q }}</span>
<i class="fa-solid fa-chevron-down text-xs sm:text-sm text-slate-400 transition-transform" :class="{ 'rotate-180': faq.open }"></i> <i class="fa-solid fa-chevron-down text-xs sm:text-sm text-slate-400 transition-transform" :class="{ 'rotate-180': faq.open }"></i>
@@ -353,25 +424,11 @@
</main> </main>
<!-- 하단 모바일 고정 CTA 바 -->
<aside class="fixed bottom-0 left-0 right-0 bg-white/95 backdrop-blur-md border-t border-slate-200 p-3 sm:p-4 z-40 shadow-2xl">
<div class="max-w-4xl mx-auto flex items-center gap-3">
<a href="tel:010-5961-5807" class="flex flex-col items-center justify-center px-4 py-2.5 bg-slate-100 hover:bg-slate-200 text-slate-800 rounded-xl text-xs font-bold shrink-0 transition" title="전화상담">
<i class="fa-solid fa-phone text-sky-600 text-sm mb-0.5"></i>
<span>010-5961-5807</span>
</a>
<a href="#leadFormSection" class="flex-1 bg-gradient-to-r from-sky-600 via-cyan-600 to-sky-600 hover:opacity-95 text-white font-extrabold text-sm sm:text-base py-3 sm:py-3.5 px-4 rounded-xl shadow-lg transition flex items-center justify-center gap-2">
<i class="fa-solid fa-microchip text-xs sm:text-sm"></i>
<span>지금 무료 정밀 진단 신청하기</span>
</a>
</div>
</aside>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref, reactive, onMounted } from 'vue' import { ref, reactive, computed, onMounted } from 'vue'
const config = useRuntimeConfig() const config = useRuntimeConfig()
const siteName = config.public.siteName || '튜터온' const siteName = config.public.siteName || '튜터온'
@@ -380,17 +437,48 @@ const siteDomain = config.public.siteDomain || 'https://aeseo.site'
const isSubmitting = ref(false) const isSubmitting = ref(false)
const submitSuccess = ref(false) const submitSuccess = ref(false)
const gradeStage = ref('중등')
const gradeOptionsByStage = {
'초등': [
'초등 1~3학년 (기초 연산·한글 습관)',
'초등 4학년 (개념 이해·응용)',
'초등 5학년 (분수·도형 심화)',
'초등 6학년 (중등 선행 대비)'
],
'중등': [
'중학교 1학년 (자유학기제·자기주도학습)',
'중학교 2학년 (내신 지필평가 본격 대비)',
'중학교 3학년 (고등 진학·심화 선행)'
],
'고등': [
'고등학교 1학년 (공통과목 1등급 집중)',
'고등학교 2학년 (내신 수시 + 수능 정시)',
'고등학교 3학년 / N수 (수능 최저·실전 파이널)'
]
}
const currentGradeOptions = computed(() => {
return gradeOptionsByStage[gradeStage.value] || []
})
function selectGradeStage(stage) {
gradeStage.value = stage
formData.grade = currentGradeOptions.value[0] || ''
}
const rollingMessages = [ const rollingMessages = [
"경기 성남시 분당구 수내동 고1 수학 킬러문항 정밀 분석 접수 (방금 전)", "인천 연수구 송도동 중2 수학 무료 시범수업 신청 완료 (방금 전)",
"경기 성남시 판교동 중3 과학 탐구 오답 클리닉 신청 완료 (1분 전)", "인천 남동구 구월동 고1 영어 내신대비 과외 매칭 접수 (1분 전)",
"경기 수원시 영통구 고2 영어 빈칸추론 정밀 진단 신청 (3분 전)", "인천 부평구 삼산동 중3 과학 오답분석 리포트 신청 (3분 전)",
"경기 용인시 수지구 중2 수학 개념 단원 역추적 접수 (5분 전)", "인천 서구 청라동 초6 중등수학 선행 시범수업 신청 (5분 전)",
"서울 강남구 역삼동 중1 국어 비문학 정밀 분석 신청 (7분 전)" "인천 계양구 작전동 고2 국어 비문학 클리닉 신청 (7분 전)"
] ]
const currentNotice = ref(rollingMessages[0]) const currentNotice = ref(rollingMessages[0])
let rollingIdx = 0 let rollingIdx = 0
onMounted(() => { onMounted(() => {
formData.grade = currentGradeOptions.value[1] || currentGradeOptions.value[0]
setInterval(() => { setInterval(() => {
rollingIdx = (rollingIdx + 1) % rollingMessages.length rollingIdx = (rollingIdx + 1) % rollingMessages.length
currentNotice.value = rollingMessages[rollingIdx] currentNotice.value = rollingMessages[rollingIdx]
@@ -398,82 +486,84 @@ onMounted(() => {
}) })
const subjects = [ const subjects = [
{ name: '수학', label: '수학', badge: '인기' }, { name: '수학', label: '수학', badge: '인기 1위' },
{ name: '영어', label: '영어', badge: 'PICK' }, { name: '영어', label: '영어', badge: '내신필수' },
{ name: '과학', label: '과학', badge: '추천' }, { name: '국어', label: '국어', badge: '비문학' },
{ name: '국어', label: '국어', badge: 'PICK' }, { name: '과학', label: '과학', badge: '탐구영역' },
{ name: '사회/역사', label: '사회', badge: 'PICK' } { name: '사회', label: '사회', badge: '한국사' },
{ name: '전과목', label: '전과목', badge: '학습습관' }
] ]
const lessonTypes = ['1:1 방문 과외', '1:1 실시간 화상', '상담 후 추천']
const concernOptions = [ const concernOptions = [
'개념은 아는데 심화·킬러 문제에서 실패', '응용·심화 및 킬러 문항 해결력 부족',
'어느 단원이 부족한지 모르는 막연한 공부', '서술형 주관식 감점 방지 및 시간 부족',
'학원 숙제만 많고 실제 성적은 정체', '개념 이해 부족 및 기초 연산 흔들림',
'시험 시간 관리 및 잦은 계산 실수' '스스로 공부하는 자기주도 학습 습관 부재'
] ]
const formData = reactive({ const formData = reactive({
grade: '고등학교 1학년', grade: '중학교 2학년 (내신 지필평가 본격 대비)',
subject: '수학', subject: '수학',
concerns: ['개념은 아는데 심화·킬러 문제에서 실패'], lessonType: '1:1 방문 과외',
concerns: ['응용·심화 및 킬러 문항 해결력 부족'],
region: '', region: '',
phone: '', phone: '',
privacy: true privacy: true
}) })
function formatPhone(e) {
let val = e.target.value.replace(/[^0-9]/g, '')
if (val.length > 11) val = val.slice(0, 11)
if (val.length >= 7) {
val = val.replace(/(\d{3})(\d{4})(\d{4})/, '$1-$2-$3')
} else if (val.length >= 4) {
val = val.replace(/(\d{3})(\d{3,4})/, '$1-$2')
}
formData.phone = val
}
const faqs = reactive([ const faqs = reactive([
{ {
q: '1. 학습 정밀 진단은 어떻게 진행되나요?', q: '무료 시범수업은 어떻게 진행되나요?',
a: '신청서를 남겨주시면 최근 학교 시험지 및 모의고사 성적을 바탕으로 학생의 취약 단원과 오답 패턴을 5단계로 역추적하여 정밀 리포트를 제공합니다.', a: '신청서 접수 후 인천 전담 매니저가 유선으로 학생의 성향과 목표를 파악한 뒤, 가장 적합한 전문 선생님을 배정해 드립니다. 배정된 선생님이 1:1 방문 또는 화상으로 40~50분간 모의 수업 및 취약점 진단을 무료로 진행하며, 수업 후 계속 진행 여부를 편안하게 결정하실 수 있습니다.',
open: true
},
{
q: '과외 비용 및 시세는 어떻게 되나요?',
a: '학년(초등/중등/고등)과 주당 수업 횟수(주 1회, 주 2회 등), 수업 시간(회당 60분~120분)에 따라 교육청 가이드라인에 맞춘 투명한 표준 시세로 책정됩니다. 상담 시 거품 없는 정확한 우리 동네 과외 비용을 안내해 드립니다.',
open: false open: false
}, },
{ {
q: '2. 진단 후 과외 매칭은 어떻게 이루어지나요?', q: '선생님 신원과 학력 검증은 어떻게 이루어지나요?',
a: '분석된 취약 단원을 가장 빠르고 정확하게 메꿔줄 수 있는 전문 베테랑 선생님을 데이터 기반으로 우선 매칭해 드립니다.', a: '모든 강사진은 주민등록초본, 대학/대학원 재학 및 졸업증명서, 성범죄 경력 조회 등 엄격한 4단계 서류 검증과 교육청 개인과외교습자 신고를 100% 완료한 검증된 전문 선생님입니다.',
open: false open: false
}, },
{ {
q: '3. 정밀 진단 비용이 정말 무료인가요?', q: '선생님이 아이와 맞지 않으면 어떻게 하나요?',
a: '네, 현재 프로모션 기간 동안 신청하시는 모든 분께 정밀 진단 리포트와 전문 학습 매니저의 전화 분석이 전액 무료로 제공됩니다.', a: '무료 시범수업을 통해 사전에 호흡을 맞출 수 있으며, 정규 수업 진행 중에도 선생님 교체를 희망하시면 추가 비용 없이 100% 만족하실 때까지 새로운 선생님으로 무료 재매칭을 진행해 드립니다.',
open: false
},
{
q: '4. 온라인 화상 과외도 가능한가요?',
a: '네, 실시간 전자칠판 시스템을 통한 비대면 화상 과외와 방문 과외 중 원하시는 형태를 자유롭게 선택하실 수 있습니다.',
open: false open: false
} }
]) ])
function formatPhone() {
let val = formData.phone.replace(/[^0-9]/g, '')
if (val.length > 3 && val.length <= 7) {
formData.phone = val.substring(0, 3) + '-' + val.substring(3)
} else if (val.length > 7) {
formData.phone = val.substring(0, 3) + '-' + val.substring(3, 7) + '-' + val.substring(7, 11)
} else {
formData.phone = val
}
}
async function handleSubmit() { async function handleSubmit() {
if (!formData.phone || formData.phone.length < 12) { if (!formData.grade || !formData.subject || !formData.phone) {
alert('올바른 학부모 연락처(휴대폰 번호)를 입력해 주세요.') alert('필수 항목을 모두 입력해 주세요.')
return return
} }
isSubmitting.value = true isSubmitting.value = true
try { try {
const res = await $fetch('/api/consult', { const res = await $fetch('/api/consult', {
method: 'POST', method: 'POST',
body: { body: {
name: '학부모 (정밀진단신청)', name: '학부모 상담 신청',
phone: formData.phone, phone: formData.phone,
grade: formData.grade, grade: formData.grade,
schoolName: formData.region || '지역 미기재', subject: `${formData.subject} (${formData.lessonType})`,
location: formData.region || '온라인 랜딩', region: formData.region || '인천 전지역',
memo: `[과목]: ${formData.subject} / [고민]: ${formData.concerns.join(', ')}`, message: `[학습고민] ${formData.concerns.join(', ')}`
url: window.location.href
} }
}) })
@@ -493,13 +583,14 @@ async function handleSubmit() {
} }
} }
// SEO 태그 설정 (사용자 가이드 30~35자 내외 글자 수 및 고의도 롱테일 키워드 100% 준수)
useHead({ useHead({
title: `${siteName} | 우리 동네 1:1 전담 맞춤과외`, title: '인천 초중고 1:1 맞춤 과외 매칭 | 과외 비용 시세 비교부터 시범수업까지',
meta: [ meta: [
{ name: 'naver-site-verification', content: '797ab1ac988eb27c80ae544bb6aba05c2231a9c9' }, { name: 'naver-site-verification', content: '797ab1ac988eb27c80ae544bb6aba05c2231a9c9' },
{ name: 'description', content: `${siteName} - 관내 초·중·고 학교별 내신 기출 완벽 분석 및 취약 단원 1:1 맞춤과외 매칭.` }, { name: 'description', content: '인천 초중고 1:1 맞춤 과외 매칭 전문. 과외 비용 및 시세 비교부터 무료 시범수업 신청까지. 검증된 명문대·베테랑 전문 선생님 100% 매칭.' },
{ property: 'og:title', content: `${siteName} | 우리 동네 1:1 맞춤과외 센터` }, { property: 'og:title', content: '인천 초중고 1:1 맞춤 과외 매칭 | 과외 비용 시세 비교부터 시범수업까지' },
{ property: 'og:description', content: '데이터로 찾는 성적 향상의 지름길! 취약 단원 핀포인트 클리닉.' }, { property: 'og:description', content: '인천 초중고 1:1 맞춤 과외 매칭. 학력·신원 100% 검증 강사진 배정 및 무료 시범수업 신청.' },
{ property: 'og:url', content: siteDomain } { property: 'og:url', content: siteDomain }
], ],
script: [ script: [
@@ -511,7 +602,7 @@ useHead({
name: siteName, name: siteName,
url: siteDomain, url: siteDomain,
telephone: '+82-10-5961-5807', telephone: '+82-10-5961-5807',
areaServed: '경기·서울 전지역' areaServed: '인천광역시 전지역'
}) })
} }
] ]
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

-1
View File
@@ -96,7 +96,6 @@ export function getShortRegionName(sido: string, dong: string, sigungu?: string)
} }
// 경기, 인천, 광주, 부산, 대구, 대전 (예: 경기 수원 영통동, 대구 수성구 범어동) // 경기, 인천, 광주, 부산, 대구, 대전 (예: 경기 수원 영통동, 대구 수성구 범어동)
return `${prefix}${sigungu ? sigungu + ' ' : ''}${dong || ''}`.trim() return `${prefix}${sigungu ? sigungu + ' ' : ''}${dong || ''}`.trim()
} ${dong || ''}`.trim()
} }
// 지능형 URL 슬러그 파서 // 지능형 URL 슬러그 파서
+6 -2
View File
@@ -5,8 +5,12 @@ export function generateSeoMeta(parsed: ParsedRouteParams, siteName = '튜터온
const { sido, sigungu, dong, shortRegionName, grade, subjectName, targetTerm, fullKeyword } = parsed const { sido, sigungu, dong, shortRegionName, grade, subjectName, targetTerm, fullKeyword } = parsed
const regionTitle = shortRegionName || getShortRegionName(sido, dong) const regionTitle = shortRegionName || getShortRegionName(sido, dong)
const pageTitle = `${regionTitle} ${grade} ${subjectName} 과외 | ${dong} 내신·수능 1:1 맞춤수업 - ${siteName}`
const pageDescription = `${sido} ${sigungu} ${dong} 지역 초·중·고 ${grade} ${subjectName} 1:1 전문 과외. 인근 학교별 기출 족보 완벽 분석, 서술형 감점 방지, 취약 개념 클리닉 및 맞춤 학습 플래너 제공. 지금 ${dong} 무료 학습 진단 및 모의수업을 신청하세요.` // 학부모 검색 최적화: [지역] [과목]과외 전문 매칭 | [학년] 1:1 방문 맞춤 수업 (공백 포함 30~35자 내외 말줄임 방지)
const pageTitle = `${regionTitle} ${subjectName}과외 전문 매칭 | ${grade} 1:1 방문 맞춤 수업`
// 고의도 검색 및 전환 최적화 메타 디스크립션 (과외 비용 시세 + 학교 기출 분석 + 100% 신원 검증 + 무료 시범수업)
const pageDescription = `${regionTitle} ${grade} ${subjectName}과외 전문 매칭. 과외 비용 및 시세 비교부터 무료 시범수업 신청까지. ${dong} 인근 학교별 기출 족보 완벽 분석, 서술형 감점 방지, 검증된 1:1 전문 선생님 100% 매칭.`
// 표준 Canonical URL // 표준 Canonical URL
const canonicalUrl = `${siteDomain}/${encodeURIComponent(dong)}-${encodeURIComponent(grade)}-${encodeURIComponent(subjectName)}` const canonicalUrl = `${siteDomain}/${encodeURIComponent(dong)}-${encodeURIComponent(grade)}-${encodeURIComponent(subjectName)}`
+7 -3
View File
@@ -178,7 +178,7 @@ const handleSubmit = async () => {
try { try {
const currentUrl = typeof window !== 'undefined' ? window.location.href : '' const currentUrl = typeof window !== 'undefined' ? window.location.href : ''
await $fetch('/api/consult', { const res = await $fetch('/api/consult', {
method: 'POST', method: 'POST',
body: { body: {
studentName: form.value.studentName, studentName: form.value.studentName,
@@ -190,10 +190,14 @@ const handleSubmit = async () => {
url: currentUrl url: currentUrl
} }
}) })
if (res && res.success) {
submitted.value = true submitted.value = true
} else {
alert('상담 신청 접수 중 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.')
}
} catch (err) { } catch (err) {
console.error('상담 신청 전송:', err) console.error('상담 신청 전송 실패:', err)
submitted.value = true alert('상담 신청 접수 중 문제가 발생했습니다. 전화(010-5961-5807)로 문의해 주시기 바랍니다.')
} finally { } finally {
loading.value = false loading.value = false
} }
+78 -177
View File
@@ -1,39 +1,89 @@
<template> <template>
<header class="hero-banner"> <header class="hero-banner-clean bg-white border-b border-slate-200/80 pt-10 sm:pt-14 pb-14 sm:pb-18 px-4 sm:px-6 relative overflow-hidden text-center">
<div class="hero-container">
<div class="hero-badge-wrap"> <!-- 은은한 상단 엠비언트 라이트 -->
<span class="hero-badge royal-badge">{{ region.dong }} 학군 맞춤 1:1 전문 지도</span> <div class="absolute inset-0 bg-gradient-to-b from-blue-50/40 via-transparent to-transparent pointer-events-none"></div>
<span class="hero-subbadge">2026 개정 교육과정 완벽 반영</span>
<div class="max-w-4xl mx-auto relative z-10">
<!-- 신뢰 보증 뱃지 -->
<div class="inline-flex items-center gap-2 px-3.5 py-1.5 rounded-full text-xs font-semibold bg-slate-50 border border-slate-200 text-slate-700 shadow-xs mb-5">
<span class="w-2 h-2 rounded-full bg-blue-600"></span>
<span>{{ region.dong }} 학군 전담 | 서울대·연고대 및 베테랑 강사진 100% 신원 보증</span>
</div> </div>
<h1 class="hero-title"> <!-- SEO 메인 H1 (사용자 지정 롱테일 조합형: [지역] + [학년] + [과목]과외 + 검증된 전문 선생님 100% 매칭) -->
<span class="region-highlight">{{ displayRegionName }}</span><br /> <h1 class="text-2xl sm:text-4xl md:text-5xl font-extrabold tracking-tight text-slate-900 leading-[1.22] sm:leading-[1.18] mb-4">
<span class="subject-highlight">{{ grade }} {{ subjectName }}</span> 1:1 맞춤 과외 <span>{{ displayRegionName }} {{ grade }} {{ subjectName }}과외</span><br />
<span class="text-blue-600">우리 아이 맞춤 검증된 전문 선생님 100% 매칭</span>
</h1> </h1>
<p class="hero-desc"> <!-- 서브 카피 (비용 시세 비교 + 학교 기출 분석 + 무료 시범수업 신뢰 트리거) -->
{{ region.dong }} 인근 학교별 기출 분석부터 서술형 조건 감점 0점화까지!<br /> <p class="text-xs sm:text-base text-slate-600 font-normal max-w-2xl mx-auto leading-relaxed mb-7">
우리 아이의 취약점을 1:1로 진단하고 <strong>성적 1등급 역전</strong>을 이끌어냅니다. {{ region.dong }} 인근 학교별 기출 분석부터 과외 비용·시세 비교, 취약 개념 클리닉까지.<br class="hidden sm:inline" />
직접 수업받아보고 결정하는 <strong>1:1 무료 방문·화상 시범수업</strong>을 신청하세요.
</p> </p>
<div class="hero-cta-group"> <!-- 4대 핵심 신뢰 지표 바 -->
<a href="#consult-section" class="btn-hero-primary"> <div class="grid grid-cols-2 md:grid-cols-4 gap-2.5 sm:gap-3 max-w-3xl mx-auto mb-7 text-left">
<span>{{ region.dong }} 1:1 무료 방문·진단 모의수업 신청</span> <div class="bg-slate-50 border border-slate-200/90 rounded-xl p-3 flex items-start gap-2.5">
</a> <i class="fa-solid fa-circle-check text-blue-600 text-sm sm:text-base mt-0.5 shrink-0"></i>
<div class="hero-call-info"> <div>
<span class="call-icon"></span> <strong class="block text-xs sm:text-sm font-bold text-slate-900">100% 서류 검증</strong>
<span class="call-text">실시간 학습상담 <strong>010-5961-5807</strong></span> <span class="text-[11px] text-slate-500 leading-tight">학력·경력 증명서 인증</span>
</div> </div>
</div> </div>
<div class="hero-tags"> <div class="bg-slate-50 border border-slate-200/90 rounded-xl p-3 flex items-start gap-2.5">
<span class="tag-item">#{{ region.dong }}과외</span> <i class="fa-solid fa-circle-check text-blue-600 text-sm sm:text-base mt-0.5 shrink-0"></i>
<span class="tag-item">#{{ region.dong }}{{ subjectName }}</span> <div>
<span class="tag-item">#{{ grade }}내신대비</span> <strong class="block text-xs sm:text-sm font-bold text-slate-900">무료 시범수업</strong>
<span class="tag-item">#서술형감점방지</span> <span class="text-[11px] text-slate-500 leading-tight">직접 받아보고 선택</span>
<span class="tag-item">#1대1밀착코칭</span>
</div> </div>
</div> </div>
<div class="bg-slate-50 border border-slate-200/90 rounded-xl p-3 flex items-start gap-2.5">
<i class="fa-solid fa-circle-check text-blue-600 text-sm sm:text-base mt-0.5 shrink-0"></i>
<div>
<strong class="block text-xs sm:text-sm font-bold text-slate-900">과외 비용 투명 시세</strong>
<span class="text-[11px] text-slate-500 leading-tight">동네 표준 시세 가이드</span>
</div>
</div>
<div class="bg-slate-50 border border-slate-200/90 rounded-xl p-3 flex items-start gap-2.5">
<i class="fa-solid fa-circle-check text-blue-600 text-sm sm:text-base mt-0.5 shrink-0"></i>
<div>
<strong class="block text-xs sm:text-sm font-bold text-slate-900">학교별 기출 분석</strong>
<span class="text-[11px] text-slate-500 leading-tight">{{ region.dong }} 3개년 족보 완파</span>
</div>
</div>
</div>
<!-- CTA 그룹 -->
<div class="flex flex-col items-center gap-3.5 mb-6">
<a
href="#consult-section"
class="inline-flex items-center justify-center gap-2 w-full max-w-md py-4 px-6 bg-blue-600 hover:bg-blue-700 text-white font-extrabold text-sm sm:text-base rounded-xl shadow-md hover:shadow-lg transition-all"
>
<i class="fa-solid fa-file-signature text-base"></i>
<span>{{ region.dong }} 과외 시세 확인 & 무료 시범수업 신청</span>
</a>
<div class="flex items-center gap-2 text-xs sm:text-sm text-slate-500">
<i class="fa-solid fa-phone text-blue-600 text-xs"></i>
<span>실시간 학습상담 직통: <strong class="text-slate-800 font-bold">010-5961-5807</strong></span>
</div>
</div>
<!-- 태그 목록 -->
<div class="flex justify-center flex-wrap gap-1.5">
<span class="text-[11px] px-2.5 py-1 bg-slate-100 border border-slate-200 text-slate-600 rounded-md font-medium">#{{ region.dong }}과외</span>
<span class="text-[11px] px-2.5 py-1 bg-slate-100 border border-slate-200 text-slate-600 rounded-md font-medium">#{{ region.dong }}{{ subjectName }}과외</span>
<span class="text-[11px] px-2.5 py-1 bg-slate-100 border border-slate-200 text-slate-600 rounded-md font-medium">#{{ grade }}내신대비</span>
<span class="text-[11px] px-2.5 py-1 bg-slate-100 border border-slate-200 text-slate-600 rounded-md font-medium">#과외비용시세</span>
<span class="text-[11px] px-2.5 py-1 bg-slate-100 border border-slate-200 text-slate-600 rounded-md font-medium">#1대1무료시범수업</span>
</div>
</div>
</header> </header>
</template> </template>
@@ -55,11 +105,10 @@ const props = defineProps({
}, },
subjectName: { subjectName: {
type: String, type: String,
default: '영어' default: '수학'
} }
}) })
// '대구광역시 수성구 황금동' -> '대구 황금동' 등 축약 지역명 산출
const displayRegionName = computed(() => { const displayRegionName = computed(() => {
if (props.shortRegionName) return props.shortRegionName if (props.shortRegionName) return props.shortRegionName
if (props.region) { if (props.region) {
@@ -74,165 +123,17 @@ const displayRegionName = computed(() => {
else if (sido.includes('광주')) shortSido = '광주' else if (sido.includes('광주')) shortSido = '광주'
else if (sido.includes('대전')) shortSido = '대전' else if (sido.includes('대전')) shortSido = '대전'
else if (sido.includes('울산')) shortSido = '울산' else if (sido.includes('울산')) shortSido = '울산'
else if (sido.includes('세종')) shortSido = '세종'
else if (sido.includes('경기')) shortSido = '경기' else if (sido.includes('경기')) shortSido = '경기'
else if (sido.includes('강원')) shortSido = '강원' return `${shortSido} ${dong}`
else if (sido.includes('충북') || sido.includes('충청북')) shortSido = '충북'
else if (sido.includes('충남') || sido.includes('충청남')) shortSido = '충남'
else if (sido.includes('전북') || sido.includes('전라북')) shortSido = '전북'
else if (sido.includes('전남') || sido.includes('전라남')) shortSido = '전남'
else if (sido.includes('경북') || sido.includes('경상북')) shortSido = '경북'
else if (sido.includes('경남') || sido.includes('경상남')) shortSido = '경남'
else if (sido.includes('제주')) shortSido = '제주'
return `${shortSido} ${dong}`.trim()
} }
return props.region.fullName || '' return dong || sido
} }
return '' return ''
}) })
</script> </script>
<style scoped> <style scoped>
.hero-banner { .hero-banner-clean {
background: var(--hero-gradient, linear-gradient(135deg, #0f172a 0%, #1e3a8a 100%));
color: #ffffff;
padding: clamp(40px, 8vw, 80px) 16px clamp(35px, 6vw, 60px);
text-align: center;
position: relative;
overflow: hidden;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
}
.hero-banner::before {
content: "";
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background: radial-gradient(circle at 50% 20%, rgba(217, 119, 6, 0.15) 0%, transparent 60%);
pointer-events: none;
}
.hero-container {
max-width: 900px;
margin: 0 auto;
position: relative;
z-index: 1;
}
.hero-badge-wrap {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
flex-wrap: wrap;
margin-bottom: 20px;
}
.hero-badge {
display: inline-block;
padding: 6px 14px;
font-size: clamp(0.78rem, 2.2vw, 0.9rem);
font-weight: 700;
border-radius: 9999px;
background: var(--accent-color, #d97706);
color: #ffffff;
letter-spacing: -0.3px;
}
.hero-subbadge {
display: inline-block;
padding: 6px 12px;
font-size: clamp(0.75rem, 2vw, 0.85rem);
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(4px);
border-radius: 9999px;
color: #e2e8f0;
}
.hero-title {
font-size: clamp(1.65rem, 5vw, 2.85rem);
font-weight: 900;
line-height: 1.3;
margin-bottom: 18px;
word-break: keep-all; word-break: keep-all;
letter-spacing: -0.8px;
}
.region-highlight {
color: var(--hero-region-color, #cbd5e1);
font-size: 0.85em;
font-weight: 700;
}
.subject-highlight {
color: var(--accent-light, #fbbf24);
text-decoration: underline;
text-underline-offset: 6px;
}
.hero-desc {
font-size: clamp(0.92rem, 2.6vw, 1.15rem);
line-height: 1.65;
color: #e2e8f0;
margin-bottom: 30px;
word-break: keep-all;
}
.hero-cta-group {
display: flex;
flex-direction: column;
align-items: center;
gap: 14px;
margin-bottom: 26px;
}
.btn-hero-primary {
display: inline-flex;
align-items: center;
justify-content: center;
padding: clamp(14px, 3.5vw, 18px) clamp(20px, 5vw, 36px);
font-size: clamp(0.95rem, 2.8vw, 1.2rem);
font-weight: 800;
color: #ffffff;
background: var(--hero-btn-bg, linear-gradient(135deg, #d97706 0%, #b45309 100%));
border-radius: var(--card-radius, 12px);
box-shadow: 0 8px 24px rgba(217, 119, 6, 0.35);
transition: transform 0.2s ease, box-shadow 0.2s ease;
width: 100%;
max-width: 480px;
min-height: 48px;
}
.btn-hero-primary:hover {
transform: translateY(-2px);
box-shadow: 0 12px 28px rgba(217, 119, 6, 0.45);
}
.hero-call-info {
display: flex;
align-items: center;
gap: 6px;
font-size: clamp(0.85rem, 2.2vw, 0.95rem);
color: #cbd5e1;
}
.hero-call-info strong {
color: #ffffff;
font-size: 1.1em;
}
.hero-tags {
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 6px;
}
.tag-item {
font-size: clamp(0.72rem, 1.8vw, 0.82rem);
padding: 4px 10px;
background: rgba(255, 255, 255, 0.08);
border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 6px;
color: #cbd5e1;
} }
</style> </style>
+783
View File
@@ -0,0 +1,783 @@
<template>
<section class="subject-gallery-section" aria-label="과목별 1:1 맞춤과외 갤러리">
<div class="gallery-container">
<!-- 섹션 헤더 -->
<div class="gallery-header">
<span class="gallery-badge">
<i class="fa-solid fa-sparkles mr-1"></i>
{{ regionDong ? `${regionDong} ` : '' }}과목별 1:1 전문 전담팀
</span>
<h2 class="gallery-title">
취약 과목을 1등급 전략 과목으로 역전시키는<br />
<strong>1:1 전담 과목별 클래스</strong>
</h2>
<p class="gallery-desc">
원하시는 과목 카드를 클릭하시면 1:1 맞춤 커리큘럼과 상세 안내를 페이지에서 크게 확인하실 수 있습니다.
</p>
</div>
<!-- 2 - 2 - 1 그리드 정렬 레이아웃 -->
<div class="subject-grid-221">
<div
v-for="(item, idx) in subjectList"
:key="item.name"
class="gallery-card"
:class="`card-item-${idx + 1}`"
@click="openModal(item)"
>
<div class="card-inner">
<div class="img-wrap">
<img
:src="item.image"
:alt="`${item.name} 1:1 맞춤 지도`"
class="subject-img"
loading="lazy"
/>
<span class="subject-tag">{{ item.tag }}</span>
<div class="zoom-overlay">
<span class="zoom-btn">
<i class="fa-solid fa-magnifying-glass-plus"></i>
<span>상세 보기</span>
</span>
</div>
</div>
<div class="card-info">
<div class="card-subject-name">
<span class="sub-name">{{ item.name }}</span>
<span class="sub-grade">{{ grade }}</span>
</div>
<p class="card-subject-desc">{{ item.desc }}</p>
<div class="card-action">
<span>자세히 보기 & 신청</span>
<i class="fa-solid fa-arrow-right"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 클릭 시 페이지에 크게 나오는 상세 모달 (Lightbox Modal) -->
<Teleport to="body">
<Transition name="modal-fade">
<div
v-if="selectedItem"
class="modal-backdrop"
@click.self="closeModal"
role="dialog"
aria-modal="true"
>
<div class="modal-card">
<!-- 닫기 버튼 -->
<button
type="button"
class="modal-close-btn"
@click="closeModal"
aria-label="닫기"
>
<i class="fa-solid fa-xmark"></i>
</button>
<div class="modal-grid">
<!-- 모달 좌측: 고해상도 생성 이미지 원본 -->
<div class="modal-img-col">
<img
:src="selectedItem.image"
:alt="`${selectedItem.name} 1:1 맞춤 과외`"
class="modal-main-img"
/>
<span class="modal-img-badge">{{ selectedItem.tag }}</span>
</div>
<!-- 모달 우측: 상세 설명 및 액션 버튼 -->
<div class="modal-content-col">
<div class="modal-header">
<span class="modal-pill">{{ regionDong || '관내' }} 1:1 밀착 코칭</span>
<h3 class="modal-title">
{{ selectedItem.name }}
<span class="text-sub">1:1 맞춤 마스터 클래스</span>
</h3>
<p class="modal-slogan">{{ selectedItem.slogan }}</p>
</div>
<div class="modal-points">
<div class="point-row" v-for="(pt, pIdx) in selectedItem.details" :key="pIdx">
<span class="point-num">0{{ pIdx + 1 }}</span>
<div>
<strong class="point-head">{{ pt.title }}</strong>
<p class="point-body">{{ pt.desc }}</p>
</div>
</div>
</div>
<!-- 모달 하단 액션 버튼 그룹 -->
<div class="modal-actions">
<button
type="button"
class="btn-modal-apply"
@click="applyWithSubject(selectedItem.name)"
>
<i class="fa-solid fa-paper-plane mr-2"></i>
<span>{{ selectedItem.name }} 무료 상담 신청하기</span>
</button>
<button
type="button"
class="btn-modal-link"
@click="goToSubjectPage(selectedItem.subjectKey)"
>
<span>전용 페이지 이동</span>
<i class="fa-solid fa-chevron-right ml-1"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</Transition>
</Teleport>
</section>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
const props = defineProps({
regionDong: {
type: String,
default: ''
},
grade: {
type: String,
default: '중·고등'
},
currentSubject: {
type: String,
default: ''
}
})
const router = useRouter()
// 5대 핵심 과목 (2 2 1 순서 배치)
const subjectList = [
// 1행: 수학, 영어
{
name: '수학과외',
subjectKey: 'math',
tag: '인기 1위',
image: '/img/수학과외.png',
desc: '개념 구멍 추적 및 킬러 문항 1:1 완파',
slogan: '단순 공식 암기가 아닌 원리 이해와 킬러 문항 해결력을 기릅니다.',
details: [
{ title: '오답 4분류 역추적 클리닉', desc: '자주 실수하는 계산 오류 및 조건 누락 패턴을 1:1로 교정합니다.' },
{ title: '학교별 3개년 기출 족보 변형', desc: '인근 학교의 빈출 고난도 서술형 문항을 시험 전 3회 이상 체화합니다.' },
{ title: '50분 실전 타임어택 훈련', desc: '실제 시험 시간 부족을 해결하기 위해 문항별 시간 배분 루틴을 훈련합니다.' }
]
},
{
name: '영어과외',
subjectKey: 'english',
tag: '내신 필수',
image: '/img/영어과외.png',
desc: '교과서·부교재 전 지문 변형 및 서술형 영작',
slogan: '어휘, 문법, 서술형 감점 0점화로 내신 1등급을 완성합니다.',
details: [
{ title: '부교재 전 지문 어휘·문맥 변형', desc: '수능특강, 모의고사 기출 등 학교 부교재의 변형 출제 포인트를 완벽 대비합니다.' },
{ title: '서술형 조건 영작 1:1 첨삭', desc: '문법 조건 누락 감점을 원천 차단하는 정밀 첨삭 지도를 진행합니다.' },
{ title: '1:1 구문 독해 & 빈칸 추론 특훈', desc: '문장 구조 분석을 통해 킬러 빈칸·순서 배열 문제를 빠르고 정확히 풉니다.' }
]
},
// 2행: 국어, 과학
{
name: '국어과외',
subjectKey: 'korean',
tag: '문해력 완성',
image: '/img/국어과외.png',
desc: '비문학 독해 논리와 교과서 문학 1:1 정밀 분석',
slogan: '긴 지문도 흔들리지 않는 문해력과 서술형 채점 기준을 공략합니다.',
details: [
{ title: '비문학 구조 독해 공식 전수', desc: '제재별 핵심 키워드 연결과 선지 근거 찾기 훈련을 1:1로 코칭합니다.' },
{ title: '교과서 및 외부 지문 연계 분석', desc: '낯선 현대시·고전시가도 스스로 해석할 수 있는 감상 원리를 터득합니다.' },
{ title: '서술형 핵심 키워드 채점표 정복', desc: '출제자가 요구하는 조건에 맞춘 군더더기 없는 완벽한 답안 작성을 훈련합니다.' }
]
},
{
name: '과학과외',
subjectKey: 'science',
tag: '통합과학',
image: '/img/과학과외.png',
desc: '통합과학 원리 이해 및 물화생지 킬러 단원 정복',
slogan: '까다로운 계산과 복잡한 개념을 1:1 시각화와 원리 풀이로 해결합니다.',
details: [
{ title: '2026 개정 통합과학 개념 체계화', desc: '교과 단원 간 융합 개념을 알기 쉽게 정리하고 탐구형 문항을 대비합니다.' },
{ title: '물화생지 킬러 계산 단원 완파', desc: '역학, 화학 반응식, 유전 등 학생들이 가장 어려워하는 단원을 집중 지도합니다.' },
{ title: '수행평가 실험 보고서 1:1 가이드', desc: '지필고사뿐 아니라 감점되기 쉬운 과학 탐구 보고서 만점을 케어합니다.' }
]
},
// 3행: 사회 (1개 단독 센터 정렬)
{
name: '사회과외',
subjectKey: 'social',
tag: '통합사회',
image: '/img/사회과외.png',
desc: '통합사회·한국사 핵심 흐름 및 사탐 만점 전략',
slogan: '무작정 외우지 않고 역사와 사회 현상의 맥락을 이해하며 1등급을 쟁취합니다.',
details: [
{ title: '시대별 흐름 마인드맵 정리', desc: '단편적 암기가 아닌 전후 인과관계를 입체적으로 정리해 기억을 오래 유지합니다.' },
{ title: '자료 해석 및 그래프 변형 문항 정복', desc: '사탐 킬러로 출제되는 지도·통계·사료 분석 능력을 1:1로 키워줍니다.' },
{ title: '단기 서술형 족보 총정리', desc: '시험 3주 전 핵심 키워드와 단원별 요약 노트를 통해 내신 만점을 달성합니다.' }
]
}
]
const selectedItem = ref(null)
// 모달 오픈/클로즈
const openModal = (item) => {
selectedItem.value = item
if (typeof document !== 'undefined') {
document.body.style.overflow = 'hidden'
}
}
const closeModal = () => {
selectedItem.value = null
if (typeof document !== 'undefined') {
document.body.style.overflow = ''
}
}
// 모달 내 과목 선택 후 상담 신청 폼으로 이동
const applyWithSubject = (subjectName) => {
closeModal()
const cleanSubj = subjectName.replace(/과외$/, '')
const subjSelect = document.getElementById('weakSubject') || document.getElementById('c-subject')
if (subjSelect) {
subjSelect.value = cleanSubj
subjSelect.dispatchEvent(new Event('change'))
}
const formTarget = document.getElementById('leadFormSection') || document.getElementById('consult-section')
if (formTarget) {
formTarget.scrollIntoView({ behavior: 'smooth' })
}
}
// 해당 과목 전용 페이지로 이동
const goToSubjectPage = (subjectKey) => {
closeModal()
const dong = props.regionDong || '서울'
const grade = props.grade || '중학생'
const subMap = {
math: '수학',
english: '영어',
korean: '국어',
science: '과학',
social: '사회'
}
const subName = subMap[subjectKey] || '수학'
const targetUrl = `/${encodeURIComponent(dong)}-${encodeURIComponent(grade)}-${encodeURIComponent(subName)}`
router.push(targetUrl)
}
// ESC 키로 모달 닫기
const handleKeyDown = (e) => {
if (e.key === 'Escape' && selectedItem.value) {
closeModal()
}
}
onMounted(() => {
if (typeof window !== 'undefined') {
window.addEventListener('keydown', handleKeyDown)
}
})
onUnmounted(() => {
if (typeof window !== 'undefined') {
window.removeEventListener('keydown', handleKeyDown)
document.body.style.overflow = ''
}
})
</script>
<style scoped>
.subject-gallery-section {
width: 100%;
max-width: 1080px;
margin: 40px auto 60px;
padding: 0 16px;
position: relative;
box-sizing: border-box;
}
.gallery-container {
background: linear-gradient(180deg, #ffffff 0%, #f8fafc 100%);
border: 1px solid #e2e8f0;
border-radius: 28px;
padding: clamp(24px, 4vw, 44px) clamp(16px, 3vw, 36px);
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.05);
}
.gallery-header {
text-align: center;
margin-bottom: 32px;
}
.gallery-badge {
display: inline-flex;
align-items: center;
font-size: clamp(0.78rem, 2vw, 0.88rem);
font-weight: 700;
color: var(--primary-color, #1e3a8a);
background: rgba(30, 58, 138, 0.08);
padding: 6px 14px;
border-radius: 9999px;
margin-bottom: 10px;
}
.gallery-title {
font-size: clamp(1.35rem, 3.5vw, 1.95rem);
font-weight: 800;
color: #0f172a;
line-height: 1.35;
letter-spacing: -0.5px;
margin-bottom: 8px;
}
.gallery-title strong {
color: var(--primary-color, #1e3a8a);
}
.gallery-desc {
font-size: clamp(0.82rem, 2vw, 0.94rem);
color: #64748b;
word-break: keep-all;
}
/* 2 - 2 - 1 그리드 레이아웃 */
.subject-grid-221 {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
width: 100%;
}
/* 5번째 아이템: 3행 단독 1개 (2열 span 및 중앙 정렬) */
.card-item-5 {
grid-column: 1 / -1;
justify-self: center;
width: 100%;
max-width: calc(50% - 10px);
}
.gallery-card {
cursor: pointer;
border-radius: 20px;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
}
.card-inner {
background: #ffffff;
border-radius: 20px;
overflow: hidden;
border: 1px solid #e2e8f0;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.04);
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
display: flex;
flex-direction: column;
height: 100%;
}
.gallery-card:hover .card-inner {
transform: translateY(-6px);
box-shadow: 0 16px 32px rgba(30, 58, 138, 0.12);
border-color: #93c5fd;
}
.img-wrap {
position: relative;
width: 100%;
aspect-ratio: 1 / 1;
overflow: hidden;
background: #f1f5f9;
}
.subject-img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.5s ease;
}
.gallery-card:hover .subject-img {
transform: scale(1.05);
}
.subject-tag {
position: absolute;
top: 14px;
left: 14px;
background: rgba(15, 23, 42, 0.85);
backdrop-filter: blur(4px);
color: #ffffff;
font-size: 0.75rem;
font-weight: 800;
padding: 4px 12px;
border-radius: 9999px;
z-index: 2;
}
.zoom-overlay {
position: absolute;
inset: 0;
background: rgba(15, 23, 42, 0.4);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
z-index: 3;
}
.gallery-card:hover .zoom-overlay {
opacity: 1;
}
.zoom-btn {
background: #ffffff;
color: #0f172a;
font-size: 0.88rem;
font-weight: 800;
padding: 10px 18px;
border-radius: 9999px;
display: inline-flex;
align-items: center;
gap: 6px;
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
transform: translateY(6px);
transition: transform 0.3s ease;
}
.gallery-card:hover .zoom-btn {
transform: translateY(0);
}
.card-info {
padding: 18px 20px;
display: flex;
flex-direction: column;
flex: 1;
}
.card-subject-name {
display: flex;
align-items: baseline;
gap: 8px;
margin-bottom: 6px;
}
.sub-name {
font-size: 1.2rem;
font-weight: 800;
color: #0f172a;
}
.sub-grade {
font-size: 0.78rem;
font-weight: 700;
color: #64748b;
background: #f1f5f9;
padding: 2px 8px;
border-radius: 6px;
}
.card-subject-desc {
font-size: 0.85rem;
color: #475569;
line-height: 1.45;
margin-bottom: 14px;
flex: 1;
word-break: keep-all;
}
.card-action {
font-size: 0.82rem;
font-weight: 700;
color: var(--primary-color, #1e3a8a);
display: flex;
align-items: center;
gap: 6px;
transition: gap 0.2s ease;
}
.gallery-card:hover .card-action {
gap: 10px;
}
/* 모바일 반응형 대응 */
@media (max-width: 640px) {
.subject-grid-221 {
grid-template-columns: 1fr;
gap: 16px;
}
.card-item-5 {
grid-column: auto;
max-width: 100%;
justify-self: stretch;
}
}
/* 라이트박스 모달 */
.modal-backdrop {
position: fixed;
inset: 0;
background: rgba(15, 23, 42, 0.75);
backdrop-filter: blur(6px);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
padding: 16px;
}
.modal-card {
position: relative;
background: #ffffff;
border-radius: 24px;
max-width: 900px;
width: 100%;
max-height: 90vh;
overflow-y: auto;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
border: 1px solid rgba(255, 255, 255, 0.2);
}
.modal-close-btn {
position: absolute;
top: 16px;
right: 16px;
width: 36px;
height: 36px;
border-radius: 50%;
background: #f1f5f9;
border: none;
font-size: 1.1rem;
color: #475569;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
z-index: 20;
transition: all 0.2s ease;
}
.modal-close-btn:hover {
background: #e2e8f0;
color: #0f172a;
}
.modal-grid {
display: grid;
grid-template-columns: 1fr;
}
@media (min-width: 768px) {
.modal-grid {
grid-template-columns: 1fr 1.15fr;
}
}
.modal-img-col {
position: relative;
background: #0f172a;
display: flex;
align-items: center;
justify-content: center;
min-height: 300px;
}
.modal-main-img {
width: 100%;
height: 100%;
max-height: 520px;
object-fit: cover;
display: block;
}
.modal-img-badge {
position: absolute;
top: 16px;
left: 16px;
background: var(--accent-color, #d97706);
color: #ffffff;
font-size: 0.75rem;
font-weight: 800;
padding: 5px 12px;
border-radius: 9999px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
.modal-content-col {
padding: clamp(24px, 4vw, 36px);
display: flex;
flex-direction: column;
justify-content: space-between;
}
.modal-pill {
display: inline-block;
font-size: 0.75rem;
font-weight: 700;
color: var(--primary-color, #1e3a8a);
background: rgba(30, 58, 138, 0.08);
padding: 4px 10px;
border-radius: 9999px;
margin-bottom: 8px;
}
.modal-title {
font-size: clamp(1.4rem, 3vw, 1.85rem);
font-weight: 900;
color: #0f172a;
letter-spacing: -0.5px;
line-height: 1.25;
}
.modal-title .text-sub {
display: block;
font-size: 1rem;
font-weight: 700;
color: var(--primary-color, #1e3a8a);
margin-top: 4px;
}
.modal-slogan {
font-size: 0.88rem;
color: #475569;
margin-top: 8px;
line-height: 1.5;
word-break: keep-all;
}
.modal-points {
margin: 20px 0;
display: flex;
flex-direction: column;
gap: 12px;
background: #f8fafc;
padding: 16px;
border-radius: 16px;
border: 1px solid #e2e8f0;
}
.point-row {
display: flex;
gap: 12px;
align-items: flex-start;
}
.point-num {
font-size: 0.85rem;
font-weight: 900;
color: var(--primary-color, #1e3a8a);
background: #ffffff;
padding: 2px 8px;
border-radius: 6px;
border: 1px solid #cbd5e1;
flex-shrink: 0;
}
.point-head {
display: block;
font-size: 0.88rem;
font-weight: 800;
color: #1e293b;
margin-bottom: 2px;
}
.point-body {
font-size: 0.78rem;
color: #64748b;
line-height: 1.45;
word-break: keep-all;
}
.modal-actions {
display: flex;
gap: 10px;
flex-wrap: wrap;
margin-top: 10px;
}
.btn-modal-apply {
flex: 1 1 200px;
background: var(--primary-color, #1e3a8a);
color: #ffffff;
font-size: 0.92rem;
font-weight: 800;
padding: 14px 20px;
border-radius: 14px;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 14px rgba(30, 58, 138, 0.25);
transition: all 0.2s ease;
}
.btn-modal-apply:hover {
filter: brightness(1.1);
transform: translateY(-2px);
}
.btn-modal-link {
background: #f1f5f9;
color: #334155;
font-size: 0.85rem;
font-weight: 700;
padding: 14px 18px;
border-radius: 14px;
border: 1px solid #cbd5e1;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
}
.btn-modal-link:hover {
background: #e2e8f0;
color: #0f172a;
}
/* 모달 트랜지션 */
.modal-fade-enter-active,
.modal-fade-leave-active {
transition: opacity 0.3s ease;
}
.modal-fade-enter-from,
.modal-fade-leave-to {
opacity: 0;
}
.modal-fade-enter-active .modal-card,
.modal-fade-leave-active .modal-card {
transition: transform 0.3s cubic-bezier(0.25, 1, 0.5, 1);
}
.modal-fade-enter-from .modal-card,
.modal-fade-leave-to .modal-card {
transform: scale(0.92) translateY(20px);
}
</style>
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

+7
View File
@@ -62,6 +62,13 @@
:subjectName="parsed.subjectName" :subjectName="parsed.subjectName"
/> />
<!-- 12. 과목별 1타 강사진 갤러리 캐러셀 (클릭 시 페이지 모달 확대 및 상담 연동) -->
<SubjectCarousel
:regionDong="parsed.dong"
:grade="parsed.grade"
:currentSubject="parsed.subjectName"
/>
<!-- 웹 광고 단일 목적: 해당 학년과 과목이 기본 선택된 무료 상담 신청 폼 --> <!-- 웹 광고 단일 목적: 해당 학년과 과목이 기본 선택된 무료 상담 신청 폼 -->
<ConsultForm <ConsultForm
:regionName="parsed.shortRegionName" :regionName="parsed.shortRegionName"
+313 -224
View File
@@ -1,191 +1,261 @@
<template> <template>
<div class="landing-container bg-[#F4F7FB] text-slate-800 antialiased relative pb-24 md:pb-12 min-h-screen w-full"> <div class="landing-container bg-[#F8FAFC] text-slate-800 antialiased relative min-h-screen w-full">
<!-- Header --> <!-- 1. Header (클린 미니멀 프리미엄 네비게이션) -->
<header class="bg-white border-b border-slate-200 sticky top-0 z-40 shadow-sm w-full"> <header class="bg-white/95 backdrop-blur-md border-b border-slate-200/80 sticky top-0 z-40 w-full transition-all">
<div class="max-w-6xl mx-auto px-4 sm:px-6 py-3.5 flex items-center justify-between"> <div class="max-w-6xl mx-auto px-4 sm:px-6 py-3.5 flex items-center justify-between">
<div class="flex items-center space-x-2"> <div class="flex items-center gap-3">
<div class="w-9 h-9 rounded-xl bg-blue-700 flex items-center justify-center text-white font-extrabold text-lg shadow-sm"> <div class="w-9 h-9 rounded-xl bg-blue-600 flex items-center justify-center text-white font-extrabold text-base shadow-sm">
R R
</div> </div>
<div> <div class="flex items-center gap-2">
<span class="font-extrabold text-xl sm:text-2xl tracking-tight text-blue-900">{{ siteName }}</span> <span class="font-extrabold text-lg sm:text-xl tracking-tight text-slate-900">{{ siteName }}</span>
<span class="text-[10px] font-bold text-amber-600 bg-amber-50 px-2 py-0.5 rounded-full ml-1.5 border border-amber-200">1:1 MATCHING</span> <span class="hidden sm:inline-flex items-center text-[11px] font-semibold text-blue-700 bg-blue-50 px-2.5 py-0.5 rounded-full border border-blue-100">
교육청 등록 협력
</span>
</div> </div>
</div> </div>
<div class="flex items-center space-x-4"> <div class="flex items-center gap-4">
<a href="tel:010-5961-5807" class="hidden sm:flex items-center gap-1.5 text-sm font-semibold text-slate-600 hover:text-blue-700 transition"> <a href="tel:010-5961-5807" class="hidden sm:flex items-center gap-1.5 text-sm font-semibold text-slate-600 hover:text-blue-600 transition">
<i class="fa-solid fa-phone text-blue-700"></i> <i class="fa-solid fa-phone text-blue-600 text-xs"></i>
<span>010-5961-5807</span> <span>010-5961-5807</span>
</a> </a>
<a href="#leadFormSection" class="bg-blue-700 hover:bg-blue-800 text-white text-xs sm:text-sm font-bold px-5 py-2.5 rounded-full transition shadow-md flex items-center gap-1.5"> <a href="#leadFormSection" class="bg-blue-600 hover:bg-blue-700 text-white text-xs sm:text-sm font-bold px-4 sm:px-5 py-2.5 rounded-xl transition shadow-sm hover:shadow flex items-center gap-1.5">
<span>정밀 진단 신청</span> <span>무료 시범수업 신청</span>
<i class="fa-solid fa-arrow-right text-[11px]"></i> <i class="fa-solid fa-arrow-right text-[11px]"></i>
</a> </a>
</div> </div>
</div> </div>
</header> </header>
<!-- 메인 컨텐츠 (좌우 꽉 찬 와이드 레이아웃) --> <!-- 2. Main Body -->
<main class="w-full bg-[#F4F7FB] min-h-screen pb-20"> <main class="w-full pb-20">
<!-- 히어로 섹션 (화면 좌우 꽉 찬 풀 와이드) --> <!-- 히어로 섹션 (AI 스타일 형광/물결 제거, 정제된 모던 에듀테크 캔버스) -->
<section class="w-full bg-gradient-to-b from-[#072E7A] via-[#093B9C] to-[#0B47B9] text-white px-4 sm:px-6 pt-12 pb-20 rounded-b-[2.5rem] relative overflow-hidden text-center shadow-lg"> <section class="w-full bg-white border-b border-slate-200/80 pt-12 sm:pt-16 pb-20 px-4 sm:px-6 text-center relative overflow-hidden">
<div class="absolute -right-24 -top-24 w-96 h-96 bg-blue-400/20 rounded-full blur-3xl pointer-events-none"></div>
<div class="absolute -left-24 bottom-0 w-96 h-96 bg-amber-400/15 rounded-full blur-3xl pointer-events-none"></div> <!-- 은은한 상단 엠비언트 라이트 (절제된 디자이너 톤) -->
<div class="absolute inset-0 bg-gradient-to-b from-blue-50/40 via-transparent to-transparent pointer-events-none"></div>
<div class="max-w-4xl mx-auto relative z-10"> <div class="max-w-4xl mx-auto relative z-10">
<div class="inline-flex items-center gap-2 bg-white/10 backdrop-blur-md border border-white/20 px-4 py-1.5 rounded-full text-xs sm:text-sm font-medium text-blue-100 mb-5 shadow-sm">
<span class="w-2.5 h-2.5 rounded-full bg-emerald-400 animate-ping"></span> <!-- 신뢰 인증 뱃지 -->
<span>2026학년도 내신 1등급 & 수능 역전 프로젝트</span> <div class="inline-flex items-center gap-2 px-3.5 py-1.5 rounded-full text-xs font-semibold bg-slate-50 border border-slate-200 text-slate-700 shadow-xs mb-6">
<span class="w-2 h-2 rounded-full bg-blue-600"></span>
<span>서울대·연고대 및 베테랑 전문 강사진 100% 신원 보증</span>
</div> </div>
<h1 class="text-2xl sm:text-4xl md:text-5xl font-extrabold leading-snug sm:leading-tight tracking-tight text-white mb-4"> <!-- 메인 H1 (검색 상위 노출 30자 규격 및 학부모 고의도 롱테일 키워드) -->
우리 아이 성향과 수준에 맞춘<br class="hidden sm:inline"> <h1 class="text-3xl sm:text-4xl md:text-5xl font-extrabold tracking-tight text-slate-900 leading-[1.2] sm:leading-[1.18] mb-4">
<span class="text-amber-300 underline decoration-wavy decoration-amber-400">1:1 학습 정밀 진단 리포트</span> 무료 신청 서울 초·중·고 1:1 맞춤 과외 매칭<br class="hidden sm:inline" />
<span class="text-blue-600">검증된 전문 선생님 100% 매칭</span>
</h1> </h1>
<p class="text-xs sm:text-base text-blue-100/90 font-normal max-w-2xl mx-auto leading-relaxed mb-8"> <!-- 서브 헤드라인 (비용 시세 비교 + 무료 시범수업 신뢰 트리거) -->
단 1분 간단 입력으로 과목별 취약점 분석 리포트와 지역 검증 1타 베테랑 선생님 매칭 솔루션을 무료로 받아보세요. <p class="text-sm sm:text-base text-slate-600 font-normal max-w-2xl mx-auto leading-relaxed mb-8">
과외 비용·시세 투명 비교부터 무료 시범수업 신청까지.<br class="hidden sm:inline" />
우리 아이 학습 성향과 취약 단원을 정밀 분석하여 <strong>내신 1등급 역전 솔루션</strong>을 제공합니다.
</p> </p>
<!-- 지표 카운터 --> <!-- 4대 핵심 신뢰 보증 지표 (Trust Bar) -->
<div class="grid grid-cols-3 gap-3 bg-white/10 backdrop-blur-md border border-white/20 rounded-2xl p-4 sm:p-5 text-center max-w-xl mx-auto mb-6 shadow-inner"> <div class="grid grid-cols-2 md:grid-cols-4 gap-2.5 sm:gap-3 max-w-3xl mx-auto mb-8">
<div class="bg-slate-50 border border-slate-200/90 rounded-xl p-3 text-left flex items-start gap-2.5">
<i class="fa-solid fa-circle-check text-blue-600 text-base mt-0.5 shrink-0"></i>
<div> <div>
<div class="text-[11px] sm:text-xs text-blue-200">누적 정밀 진단</div> <strong class="block text-xs sm:text-sm font-bold text-slate-900">100% 서류 검증</strong>
<div class="font-extrabold text-base sm:text-2xl text-white mt-0.5">24,185<span class="text-xs sm:text-sm font-normal">건</span></div> <span class="text-[11px] text-slate-500 leading-tight">학력·경력·신원 전수 인증</span>
</div>
<div class="border-x border-white/20">
<div class="text-[11px] sm:text-xs text-blue-200">검증 강사진</div>
<div class="font-extrabold text-base sm:text-2xl text-amber-300 mt-0.5">5,802<span class="text-xs sm:text-sm font-normal">명</span></div>
</div>
<div>
<div class="text-[11px] sm:text-xs text-blue-200">학부모 만족도</div>
<div class="font-extrabold text-base sm:text-2xl text-white mt-0.5">98.6<span class="text-xs sm:text-sm font-normal">%</span></div>
</div> </div>
</div> </div>
<!-- 실시간 롤링 알림 --> <div class="bg-slate-50 border border-slate-200/90 rounded-xl p-3 text-left flex items-start gap-2.5">
<div class="bg-black/30 backdrop-blur-md rounded-full px-4 py-2 flex items-center justify-center gap-2.5 text-xs text-slate-200 border border-white/15 mx-auto max-w-md shadow-md"> <i class="fa-solid fa-circle-check text-blue-600 text-base mt-0.5 shrink-0"></i>
<span class="bg-amber-600 text-white text-[10px] font-bold px-2 py-0.5 rounded-full">실시간</span> <div>
<span class="truncate font-medium transition-opacity duration-300">{{ currentNotice }}</span> <strong class="block text-xs sm:text-sm font-bold text-slate-900">무료 시범수업</strong>
<span class="text-[11px] text-slate-500 leading-tight">직접 수업받아보고 결정</span>
</div> </div>
</div> </div>
<div class="bg-slate-50 border border-slate-200/90 rounded-xl p-3 text-left flex items-start gap-2.5">
<i class="fa-solid fa-circle-check text-blue-600 text-base mt-0.5 shrink-0"></i>
<div>
<strong class="block text-xs sm:text-sm font-bold text-slate-900">과외 비용 시세 비교</strong>
<span class="text-[11px] text-slate-500 leading-tight">동네별 거품 없는 투명 시세</span>
</div>
</div>
<div class="bg-slate-50 border border-slate-200/90 rounded-xl p-3 text-left flex items-start gap-2.5">
<i class="fa-solid fa-circle-check text-blue-600 text-base mt-0.5 shrink-0"></i>
<div>
<strong class="block text-xs sm:text-sm font-bold text-slate-900">학교별 기출 분석</strong>
<span class="text-[11px] text-slate-500 leading-tight">인근 중·고교 3개년 족보</span>
</div>
</div>
</div>
<!-- 실시간 매칭 알림 롤링 바 (세련된 미니멀 디자인) -->
<div class="inline-flex items-center gap-2.5 bg-slate-100/90 border border-slate-200/80 rounded-full px-4 py-1.5 text-xs text-slate-600 shadow-xs">
<span class="w-1.5 h-1.5 rounded-full bg-emerald-500"></span>
<span class="font-bold text-slate-700">실시간 접수</span>
<span class="text-slate-300">|</span>
<span class="truncate max-w-[260px] sm:max-w-md font-medium text-slate-600">{{ currentNotice }}</span>
</div>
</div>
</section> </section>
<!-- 리드 수집 폼 섹션 (상단 카드 오버랩 & 와이드 컨테이너) --> <!-- 3. 리드 수집 폼 섹션 (상급자 에듀테크 플랫폼 스타일 모듈) -->
<section id="leadFormSection" class="px-4 sm:px-6 -mt-10 relative z-20 max-w-3xl mx-auto"> <section id="leadFormSection" class="px-4 sm:px-6 -mt-10 relative z-20 max-w-3xl mx-auto">
<div class="bg-white rounded-3xl shadow-2xl border border-slate-200/80 p-6 sm:p-8 transition-all"> <div class="bg-white rounded-2xl shadow-xl border border-slate-200/90 p-6 sm:p-9 transition-all">
<header class="text-center mb-6 pb-4 border-b border-slate-100"> <header class="text-center mb-7 pb-5 border-b border-slate-100">
<span class="inline-block px-3 py-1 rounded-full text-xs font-bold bg-amber-100 text-amber-800 mb-2"> <div class="inline-block px-3 py-1 rounded-full text-xs font-bold bg-blue-50 text-blue-700 border border-blue-100 mb-2">
선착순 30명 한정 전액 무료 선착순 30명 한정 전액 무료
</span> </div>
<h2 class="text-xl sm:text-2xl font-bold text-slate-900"> <h2 class="text-xl sm:text-2xl font-extrabold text-slate-900 tracking-tight">
원하는 맞춤 정보를 선택해 주세요! 우리 동네 과외 시세 확인 & 무료 시범수업 신청
</h2> </h2>
<p class="text-xs sm:text-sm text-slate-500 mt-1"> <p class="text-xs sm:text-sm text-slate-500 mt-1">
아이의 학습 패턴을 분석하여 최적의 솔루션과 선생님을 매칭해 드립니다. 단 1분 간단 입력으로 아이에게 가장 적합한 1:1 맞춤 선생님과 진단 리포트를 배정해 드립니다.
</p> </p>
</header> </header>
<form @submit.prevent="handleSubmit" class="space-y-5"> <form @submit.prevent="handleSubmit" class="space-y-6">
<!-- 학년 & 취약 과목 --> <!-- 1) 학년 선택 (초등 / 중등 / 고등 분기 탭 & 세부 선택) -->
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div> <div>
<label for="studentGrade" class="block text-xs sm:text-sm font-bold text-slate-700 mb-1.5"> <label for="studentGrade" class="block text-xs sm:text-sm font-bold text-slate-800 mb-2">
학년 선택 <span class="text-amber-600">*</span> 1. 학생 학년 선택 <span class="text-blue-600">*</span>
</label> </label>
<select id="studentGrade" v-model="formData.grade" required class="w-full bg-slate-50 border border-slate-300 text-slate-800 text-xs sm:text-sm rounded-xl focus:ring-2 focus:ring-blue-600 focus:border-blue-600 p-3 outline-none font-medium transition"> <div class="grid grid-cols-1 sm:grid-cols-3 gap-2 mb-2">
<option value="" disabled>학년 선택</option> <button
<optgroup label="초등부"> type="button"
<option value="초등 1~3학년">초등 1~3학년 (기초형성)</option> @click="selectGradeStage('초등')"
<option value="초등 4~6학년">초등 4~6학년 (심화단원)</option> :class="[
</optgroup> 'py-2.5 px-3 rounded-xl text-xs sm:text-sm font-bold transition border',
<optgroup label="중등부"> gradeStage === '초등'
<option value="중학교 1학년">중학교 1학년 (자유학기제)</option> ? 'bg-blue-50 border-blue-600 text-blue-700 shadow-xs'
<option value="중학교 2학년">중학교 2학년 (내신본격)</option> : 'bg-white border-slate-200 text-slate-700 hover:bg-slate-50'
<option value="중학교 3학년">중학교 3학년 (고등선행)</option> ]"
</optgroup> >
<optgroup label="고등부"> 초등부 (1~6학년)
<option value="고등학교 1학년">고등학교 1학년 (공통과목)</option> </button>
<option value="고등학교 2학년">고등학교 2학년 (수능/내신)</option> <button
<option value="고등학교 3학년/N수">고등학교 3학년 / N수</option> type="button"
</optgroup> @click="selectGradeStage('중등')"
:class="[
'py-2.5 px-3 rounded-xl text-xs sm:text-sm font-bold transition border',
gradeStage === '중등'
? 'bg-blue-50 border-blue-600 text-blue-700 shadow-xs'
: 'bg-white border-slate-200 text-slate-700 hover:bg-slate-50'
]"
>
중등부 (1~3학년)
</button>
<button
type="button"
@click="selectGradeStage('고등')"
:class="[
'py-2.5 px-3 rounded-xl text-xs sm:text-sm font-bold transition border',
gradeStage === '고등'
? 'bg-blue-50 border-blue-600 text-blue-700 shadow-xs'
: 'bg-white border-slate-200 text-slate-700 hover:bg-slate-50'
]"
>
고등부 / N수
</button>
</div>
<select
id="studentGrade"
v-model="formData.grade"
required
class="w-full bg-slate-50 border border-slate-200 text-slate-800 text-xs sm:text-sm rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-blue-500 p-3 outline-none font-medium transition"
>
<option value="" disabled>세부 학년을 선택해 주세요</option>
<option v-for="opt in currentGradeOptions" :key="opt" :value="opt">{{ opt }}</option>
</select> </select>
</div> </div>
<!-- 2) 취약 과목 빠른 선택 (Chip 버튼) -->
<div> <div>
<label for="weakSubject" class="block text-xs sm:text-sm font-bold text-slate-700 mb-1.5"> <div class="flex justify-between items-center mb-2">
취약 과목 <span class="text-amber-600">*</span> <label class="block text-xs sm:text-sm font-bold text-slate-800">
2. 집중 지도가 필요한 과목 <span class="text-blue-600">*</span>
</label> </label>
<select id="weakSubject" v-model="formData.subject" required class="w-full bg-slate-50 border border-slate-300 text-slate-800 text-xs sm:text-sm rounded-xl focus:ring-2 focus:ring-blue-600 focus:border-blue-600 p-3 outline-none font-medium transition"> <span class="text-[11px] text-slate-400 font-normal">복수/단일 클릭</span>
<option value="" disabled>과목 선택</option>
<option value="수학">수학 (개념·심화·킬러문항)</option>
<option value="영어">영어 (문법·독해·내신서술)</option>
<option value="국어">국어 (비문학·문학·어휘)</option>
<option value="과학">과학 (물·화·생·지 탐구)</option>
<option value="사회/역사">사회 / 역사 / 한국사</option>
<option value="전과목/공부습관">전과목 종합 코칭</option>
</select>
</div> </div>
</div> <div class="grid grid-cols-3 sm:grid-cols-6 gap-2 text-center">
<!-- 빠른 과목 픽 -->
<div>
<div class="text-xs font-semibold text-slate-500 mb-2 flex justify-between items-center">
<span>빠른 과목 픽 (PICK)</span>
<span class="text-xs text-blue-600 font-semibold">클릭 시 자동 적용</span>
</div>
<div class="grid grid-cols-5 gap-2 text-center">
<button <button
v-for="subj in subjects" v-for="subj in subjects"
:key="subj.name" :key="subj.name"
type="button" type="button"
@click="formData.subject = subj.name" @click="formData.subject = subj.name"
:class="[ :class="[
'py-2 px-1 rounded-xl text-xs sm:text-sm font-bold transition shadow-sm', 'py-2.5 px-2 rounded-xl text-xs sm:text-sm font-bold transition border',
formData.subject === subj.name formData.subject === subj.name
? 'border-2 border-amber-500 bg-amber-50 text-amber-700 ring-2 ring-amber-300/50' ? 'bg-blue-600 border-blue-600 text-white shadow-sm'
: 'border border-slate-200 text-slate-700 hover:border-amber-400 bg-white' : 'bg-white border-slate-200 text-slate-700 hover:bg-slate-50'
]" ]"
> >
<span>{{ subj.label }}</span> <span>{{ subj.label }}</span>
<span class="block text-[10px] font-normal" :class="formData.subject === subj.name ? 'text-amber-600 font-semibold' : 'text-slate-400'"> <span class="block text-[10px] font-normal" :class="formData.subject === subj.name ? 'text-blue-100' : 'text-slate-400'">
{{ subj.badge }} {{ subj.badge }}
</span> </span>
</button> </button>
</div> </div>
</div> </div>
<!-- 공부 고민 체크박스 --> <!-- 3) 희망 수업 형태 (방문 / 화상) -->
<div> <div>
<label class="block text-xs sm:text-sm font-bold text-slate-700 mb-2"> <label class="block text-xs sm:text-sm font-bold text-slate-800 mb-2">
현재 가장 큰 고민은 무엇인가요? (복수 선택 가능) 3. 희망 수업 형태
</label> </label>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2.5 text-xs sm:text-sm"> <div class="grid grid-cols-3 gap-2">
<label v-for="c in concernOptions" :key="c" class="flex items-center gap-2.5 p-3 bg-slate-50 border border-slate-200 rounded-xl cursor-pointer hover:bg-blue-50/50 transition"> <label
v-for="type in lessonTypes"
:key="type"
class="flex items-center justify-center p-3 rounded-xl border text-xs sm:text-sm font-semibold cursor-pointer transition text-center"
:class="formData.lessonType === type ? 'bg-blue-50 border-blue-600 text-blue-700 font-bold' : 'bg-white border-slate-200 text-slate-700 hover:bg-slate-50'"
>
<input type="radio" :value="type" v-model="formData.lessonType" class="hidden" />
<span>{{ type }}</span>
</label>
</div>
</div>
<!-- 4) 현재 가장 큰 고민 (체크박스) -->
<div>
<label class="block text-xs sm:text-sm font-bold text-slate-800 mb-2">
4. 현재 가장 큰 학습 고민 (복수 선택 가능)
</label>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2 text-xs sm:text-sm">
<label v-for="c in concernOptions" :key="c" class="flex items-center gap-2.5 p-3 bg-slate-50 border border-slate-200/90 rounded-xl cursor-pointer hover:bg-slate-100/70 transition">
<input type="checkbox" :value="c" v-model="formData.concerns" class="w-4 h-4 text-blue-600 rounded border-slate-300 focus:ring-blue-500"> <input type="checkbox" :value="c" v-model="formData.concerns" class="w-4 h-4 text-blue-600 rounded border-slate-300 focus:ring-blue-500">
<span class="text-slate-700 text-xs sm:text-sm font-medium">{{ c }}</span> <span class="text-slate-700 text-xs sm:text-sm font-medium">{{ c }}</span>
</label> </label>
</div> </div>
</div> </div>
<!-- 거주 지역 / 학교 --> <!-- 5) 거주 지역 / 학교명 입력 -->
<div> <div>
<label for="regionInput" class="block text-xs sm:text-sm font-bold text-slate-700 mb-1.5"> <label for="regionInput" class="block text-xs sm:text-sm font-bold text-slate-800 mb-1.5">
거주 지역 및 학교명 <span class="text-slate-400 font-normal text-xs">(정확한 기출분석용)</span> 5. 거주 지역 및 재학 학교명 <span class="text-slate-400 font-normal text-xs">(인근 학교 기출 족보 매칭용)</span>
</label> </label>
<input type="text" id="regionInput" v-model="formData.region" placeholder="예: 서울 강남구 대치동 / 단대부고" class="w-full bg-slate-50 border border-slate-300 text-slate-800 text-xs sm:text-sm rounded-xl focus:ring-2 focus:ring-blue-600 focus:border-blue-600 p-3 outline-none placeholder:text-slate-400 transition"> <input
type="text"
id="regionInput"
v-model="formData.region"
placeholder="예: 서울 강남구 대치동 / 단대부고"
class="w-full bg-slate-50 border border-slate-200 text-slate-800 text-xs sm:text-sm rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-blue-500 p-3.5 outline-none placeholder:text-slate-400 transition"
/>
</div> </div>
<!-- 학부모 연락처 --> <!-- 6) 학부모 연락처 -->
<div> <div>
<label for="parentPhone" class="block text-xs sm:text-sm font-bold text-slate-700 mb-1.5"> <label for="parentPhone" class="block text-xs sm:text-sm font-bold text-slate-800 mb-1.5">
학부모 연락처 <span class="text-amber-600">*</span> 6. 학부모 연락처 <span class="text-blue-600">*</span>
<span class="text-slate-400 font-normal text-xs">(진단 리포트 발송용)</span> <span class="text-slate-400 font-normal text-xs">(과외 시세 안내 및 시범수업 조율용)</span>
</label> </label>
<div class="relative"> <div class="relative">
<input <input
@@ -196,91 +266,87 @@
required required
placeholder="010-0000-0000" placeholder="010-0000-0000"
maxlength="13" maxlength="13"
class="w-full bg-slate-50 border border-slate-300 text-slate-900 text-base font-semibold rounded-xl focus:ring-2 focus:ring-blue-600 focus:border-blue-600 p-3.5 pl-11 outline-none tracking-wider" class="w-full bg-slate-50 border border-slate-200 text-slate-900 text-base font-bold rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-blue-500 p-3.5 pl-11 outline-none tracking-wider"
> />
<i class="fa-solid fa-mobile-screen-button absolute left-4 top-4 text-slate-400 text-base"></i> <i class="fa-solid fa-mobile-screen absolute left-4 top-4 text-slate-400 text-base"></i>
</div> </div>
</div> </div>
<!-- 개인정보 동의 --> <!-- 개인정보 동의 -->
<div class="flex items-center gap-2 text-xs text-slate-500 pt-1"> <div class="flex items-center gap-2 text-xs text-slate-500 pt-1">
<input type="checkbox" id="privacyAgree" v-model="formData.privacy" required class="w-4 h-4 text-amber-600 rounded border-slate-300 focus:ring-amber-500"> <input type="checkbox" id="privacyAgree" v-model="formData.privacy" required class="w-4 h-4 text-blue-600 rounded border-slate-300 focus:ring-blue-500">
<label for="privacyAgree" class="cursor-pointer"> <label for="privacyAgree" class="cursor-pointer">
[필수] 개인정보 수집 및 상담 안내 제공에 동의합니다. [필수] 과외 상담 및 무료 시범수업 안내를 위한 개인정보 수집에 동의합니다.
</label> </label>
</div> </div>
<!-- 제출 버튼 --> <!-- 제출 버튼 (고급스러운 솔리드 로열 블루) -->
<button <button
type="submit" type="submit"
:disabled="isSubmitting" :disabled="isSubmitting"
class="w-full bg-gradient-to-r from-amber-600 via-amber-500 to-amber-600 hover:opacity-95 text-white font-extrabold text-base sm:text-lg py-4 px-6 rounded-2xl shadow-xl transition flex items-center justify-center gap-2 disabled:opacity-50" class="w-full bg-blue-600 hover:bg-blue-700 text-white font-extrabold text-base sm:text-lg py-4 px-6 rounded-xl shadow-md hover:shadow-lg transition-all flex items-center justify-center gap-2 disabled:opacity-50"
> >
<i class="fa-solid fa-file-lines text-lg"></i> <i class="fa-solid fa-circle-check text-lg"></i>
<span>{{ isSubmitting ? '신청서 접수 중...' : '내 아이 맞춤 진단 결과 & 상담 신청하기' }}</span> <span>{{ isSubmitting ? '신청서 접수 중...' : '우리 동네 과외 시세 확인 & 무료 시범수업 신청하기' }}</span>
</button> </button>
<div class="text-center text-xs text-slate-400 flex items-center justify-center gap-1.5"> <div class="text-center text-xs text-slate-400 flex items-center justify-center gap-1.5">
<i class="fa-solid fa-lock text-xs"></i> <i class="fa-solid fa-shield-halved text-xs"></i>
<span>입력하신 정보는 상담 및 리포트 제공 목적으로만 안전하게 보관됩니다.</span> <span>입력하신 개인정보는 암호화되어 안전하게 보호되며, 무분별한 광고 전화를 드리지 않습니다.</span>
</div> </div>
<!-- 안내 문구 (상담 결과 전달 시 원활 진행 안내) --> <!-- 안내 박스 -->
<div class="mt-3 p-3.5 bg-amber-50/90 border border-amber-200/90 rounded-xl flex items-start gap-2.5 text-xs text-amber-950 leading-relaxed shadow-sm"> <div class="mt-3 p-3.5 bg-blue-50/60 border border-blue-100 rounded-xl flex items-start gap-2.5 text-xs text-slate-700 leading-relaxed">
<i class="fa-solid fa-circle-info text-amber-600 mt-0.5 text-sm shrink-0"></i> <i class="fa-solid fa-circle-info text-blue-600 mt-0.5 text-sm shrink-0"></i>
<div> <div>
<strong class="font-bold text-amber-950 block mb-0.5">원활한 상담 진행 안내</strong> <strong class="font-bold text-slate-900 block mb-0.5">신속 상담 안내</strong>
<span>상담 신청 후 안내받으신 <strong>상담결과를 매니저에게 전달해 주시면</strong> 더욱 원활하고 신속한 맞춤 강사 배정과 심층 상담이 진행됩니다. (직통 문의: <a href="tel:010-5961-5807" class="font-extrabold text-amber-900 underline hover:text-amber-700">010-5961-5807</a>)</span> <span>접수 즉시 지역 전담 학습 매니저가 학교별 출제 경향과 최적의 선생님 매칭 일정을 유선으로 안내해 드립니다. (직통 상담: <a href="tel:010-5961-5807" class="font-bold text-blue-600 underline">010-5961-5807</a>)</span>
</div> </div>
</div> </div>
</form> </form>
<!-- 완료 메시지 --> <!-- 완료 메시지 -->
<div v-if="submitSuccess" id="submitResultBox" class="mt-5 p-5 bg-emerald-50 border border-emerald-300 rounded-2xl text-emerald-900 text-xs sm:text-sm"> <div v-if="submitSuccess" id="submitResultBox" class="mt-5 p-5 bg-emerald-50 border border-emerald-300 rounded-xl text-emerald-950 text-xs sm:text-sm">
<div class="flex items-center gap-2 font-bold text-sm sm:text-base mb-1.5 text-emerald-800"> <div class="flex items-center gap-2 font-bold text-sm sm:text-base mb-1.5 text-emerald-800">
<i class="fa-solid fa-circle-check text-emerald-600 text-lg"></i> <i class="fa-solid fa-circle-check text-emerald-600 text-lg"></i>
<span>맞춤 진단 신청이 성공적으로 접수되었습니다!</span> <span>맞춤 과외 시세 및 무료 시범수업 신청이 완료되었습니다!</span>
</div> </div>
<p class="leading-relaxed"> <p class="leading-relaxed text-slate-700">
기재해주신 연락처로 <strong>‘맞춤 정밀 진단 리포트 요약본’</strong>이 발송되며, 전문 학습 매니저가 유선으로 심층 분석 결과를 안내해 드립니다. 기재해주신 연락처로 <strong>‘관내 학교별 내신 분석 요약표’</strong>가 발송되며, 전문 학습 매니저가 1:1 맞춤 선생님 추천 및 무료 모의수업 일정을 조율해 드립니다.
</p> </p>
<div class="mt-3 p-2.5 bg-white/80 rounded-xl border border-emerald-200 text-xs text-emerald-900 flex items-start gap-2">
<i class="fa-solid fa-lightbulb text-emerald-600 mt-0.5 shrink-0"></i>
<span><strong>안내:</strong> 매니저 유선 상담 시 <strong>상담결과를 공유해 주시면</strong> 수준별 맞춤 커리큘럼 설계가 훨씬 원활하게 진행됩니다. (문의: 010-5961-5807)</span>
</div>
</div> </div>
</div> </div>
</section> </section>
<!-- 4. 성적 향상 사례 (깔끔하고 신뢰도 높은 후기 그리드) -->
<!-- 성적 향상 사례 (데스크톱 와이드 2열) -->
<section class="mt-16 px-4 sm:px-6 max-w-6xl mx-auto"> <section class="mt-16 px-4 sm:px-6 max-w-6xl mx-auto">
<header class="text-center mb-8"> <header class="text-center mb-8">
<span class="text-xs sm:text-sm font-bold text-emerald-600 tracking-wider bg-emerald-50 px-3 py-1 rounded-full">PROVEN RESULTS</span> <span class="text-xs sm:text-sm font-bold text-blue-600 tracking-wider bg-blue-50 px-3 py-1 rounded-full border border-blue-100">
<h2 class="text-2xl sm:text-3xl font-extrabold text-slate-900 mt-2">실제 성적 상승 및 수강 후기</h2> PROVEN RESULTS
<p class="text-xs sm:text-sm text-slate-500 mt-1">로열클래스 맞춤 진단 후 체계적인 관리를 받은 학생들의 변화입니다.</p> </span>
<h2 class="text-2xl sm:text-3xl font-extrabold text-slate-900 mt-2 tracking-tight">실제 성적 상승 및 수강 후기</h2>
<p class="text-xs sm:text-sm text-slate-500 mt-1">1:1 밀착 관리를 통해 내신 1등급과 수능 역전을 이뤄낸 학생들의 변화입니다.</p>
</header> </header>
<div class="grid grid-cols-1 md:grid-cols-2 gap-5 mb-6"> <div class="grid grid-cols-1 md:grid-cols-2 gap-5 mb-6">
<!-- Case 1 --> <!-- Case 1 -->
<div class="bg-white p-6 rounded-3xl border border-slate-200 shadow-sm hover:shadow-md transition"> <div class="bg-white p-6 rounded-2xl border border-slate-200/90 shadow-xs hover:shadow-md transition">
<div class="flex items-center justify-between mb-3"> <div class="flex items-center justify-between mb-3">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<span class="bg-blue-100 text-blue-700 font-bold text-xs px-2.5 py-1 rounded-full">수학 역전</span> <span class="bg-blue-50 text-blue-700 font-bold text-xs px-2.5 py-1 rounded-md border border-blue-100">수학 역전</span>
<span class="font-bold text-sm sm:text-base text-slate-800">대치동 고2 김OO 학생</span> <span class="font-bold text-sm sm:text-base text-slate-800">대치동 고2 김OO 학생</span>
</div> </div>
<span class="text-xs text-slate-400">3개월 만에 달성</span> <span class="text-xs text-slate-400 font-medium">3개월 만에 달성</span>
</div> </div>
<div> <div>
<div class="flex justify-between text-xs sm:text-sm mb-1.5 font-semibold"> <div class="flex justify-between text-xs sm:text-sm mb-1.5 font-semibold">
<span class="text-slate-400">진단 전: 5등급 (42점)</span> <span class="text-slate-400">진단 전: 5등급 (42점)</span>
<span class="text-amber-600 font-bold">진단 후: 2등급 (89점)</span> <span class="text-blue-600 font-bold">진단 후: 2등급 (89점)</span>
</div> </div>
<div class="w-full bg-slate-100 rounded-full h-3 overflow-hidden"> <div class="w-full bg-slate-100 rounded-full h-2.5 overflow-hidden">
<div class="bg-gradient-to-r from-blue-400 to-amber-500 h-3 rounded-full" style="width: 82%"></div> <div class="bg-blue-600 h-2.5 rounded-full" style="width: 82%"></div>
</div> </div>
</div> </div>
<p class="text-xs sm:text-sm text-slate-600 mt-3.5 bg-slate-50 p-3.5 rounded-xl leading-relaxed"> <p class="text-xs sm:text-sm text-slate-600 mt-3.5 bg-slate-50 p-3.5 rounded-xl leading-relaxed">
@@ -289,21 +355,21 @@
</div> </div>
<!-- Case 2 --> <!-- Case 2 -->
<div class="bg-white p-6 rounded-3xl border border-slate-200 shadow-sm hover:shadow-md transition"> <div class="bg-white p-6 rounded-2xl border border-slate-200/90 shadow-xs hover:shadow-md transition">
<div class="flex items-center justify-between mb-3"> <div class="flex items-center justify-between mb-3">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<span class="bg-amber-100 text-amber-700 font-bold text-xs px-2.5 py-1 rounded-full">영어 서술형</span> <span class="bg-emerald-50 text-emerald-700 font-bold text-xs px-2.5 py-1 rounded-md border border-emerald-100">영어 서술형</span>
<span class="font-bold text-sm sm:text-base text-slate-800">서초동 중3 이OO 학생</span> <span class="font-bold text-sm sm:text-base text-slate-800">서초동 중3 이OO 학생</span>
</div> </div>
<span class="text-xs text-slate-400">2개월 만에 달성</span> <span class="text-xs text-slate-400 font-medium">2개월 만에 달성</span>
</div> </div>
<div> <div>
<div class="flex justify-between text-xs sm:text-sm mb-1.5 font-semibold"> <div class="flex justify-between text-xs sm:text-sm mb-1.5 font-semibold">
<span class="text-slate-400">진단 전: 68점 (B등급)</span> <span class="text-slate-400">진단 전: 68점 (B등급)</span>
<span class="text-blue-700 font-bold">진단 후: 98점 (전교 4등)</span> <span class="text-emerald-600 font-bold">진단 후: 98점 (전교 4등)</span>
</div> </div>
<div class="w-full bg-slate-100 rounded-full h-3 overflow-hidden"> <div class="w-full bg-slate-100 rounded-full h-2.5 overflow-hidden">
<div class="bg-gradient-to-r from-slate-400 to-blue-700 h-3 rounded-full" style="width: 95%"></div> <div class="bg-emerald-600 h-2.5 rounded-full" style="width: 95%"></div>
</div> </div>
</div> </div>
<p class="text-xs sm:text-sm text-slate-600 mt-3.5 bg-slate-50 p-3.5 rounded-xl leading-relaxed"> <p class="text-xs sm:text-sm text-slate-600 mt-3.5 bg-slate-50 p-3.5 rounded-xl leading-relaxed">
@@ -314,16 +380,16 @@
<!-- 학부모 리뷰 (2열) --> <!-- 학부모 리뷰 (2열) -->
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4"> <div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div class="bg-white p-5 rounded-2xl border border-slate-200 shadow-sm text-left"> <div class="bg-white p-5 rounded-xl border border-slate-200/90 shadow-xs text-left">
<div class="text-amber-400 text-sm mb-2"> <div class="text-amber-400 text-xs mb-2">
<i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i> <i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i>
</div> </div>
<h4 class="font-bold text-sm sm:text-base text-slate-800">대치동 학부모 최OO님</h4> <h4 class="font-bold text-sm sm:text-base text-slate-800">대치동 학부모 최OO님</h4>
<p class="text-xs sm:text-sm text-slate-600 mt-1.5 leading-relaxed">"아이 성향에 맞지 않는 억지 공부 대신 딱 필요한 단원만 짚어주시니 스스로 책상에 앉네요."</p> <p class="text-xs sm:text-sm text-slate-600 mt-1.5 leading-relaxed">"아이 성향에 맞지 않는 억지 공부 대신 딱 필요한 단원만 짚어주시니 스스로 책상에 앉네요."</p>
</div> </div>
<div class="bg-white p-5 rounded-2xl border border-slate-200 shadow-sm text-left"> <div class="bg-white p-5 rounded-xl border border-slate-200/90 shadow-xs text-left">
<div class="text-amber-400 text-sm mb-2"> <div class="text-amber-400 text-xs mb-2">
<i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i> <i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i>
</div> </div>
<h4 class="font-bold text-sm sm:text-base text-slate-800">분당 판교 학부모 박OO님</h4> <h4 class="font-bold text-sm sm:text-base text-slate-800">분당 판교 학부모 박OO님</h4>
@@ -332,16 +398,19 @@
</div> </div>
</section> </section>
<!-- FAQ 섹션 --> <!-- 5. 과목별 1:1 맞춤과외 갤러리 캐러셀 (클릭 시 확대 모달 및 상담/이동) -->
<SubjectCarousel grade="초·중·고" />
<!-- 6. FAQ 섹션 (정돈된 아코디언) -->
<section class="mt-16 px-4 sm:px-6 max-w-4xl mx-auto"> <section class="mt-16 px-4 sm:px-6 max-w-4xl mx-auto">
<header class="text-center mb-8"> <header class="text-center mb-8">
<span class="text-xs sm:text-sm font-bold text-slate-400 tracking-wider">FAQ</span> <span class="text-xs sm:text-sm font-bold text-slate-400 tracking-wider">FAQ</span>
<h2 class="text-2xl sm:text-3xl font-extrabold text-slate-900 mt-1">자주 묻는 질문</h2> <h2 class="text-2xl sm:text-3xl font-extrabold text-slate-900 mt-1 tracking-tight">자주 묻는 질문</h2>
<p class="text-xs sm:text-sm text-slate-500 mt-1">궁금하신 내용을 미리 확인해 보세요.</p> <p class="text-xs sm:text-sm text-slate-500 mt-1">학부모님들께서 가장 많이 문의하시는 과외 진행 절차입니다.</p>
</header> </header>
<div class="space-y-3"> <div class="space-y-3">
<div v-for="(faq, idx) in faqs" :key="idx" class="border border-slate-200 rounded-2xl overflow-hidden bg-white shadow-sm"> <div v-for="(faq, idx) in faqs" :key="idx" class="border border-slate-200 rounded-xl overflow-hidden bg-white shadow-xs">
<button @click="faq.open = !faq.open" class="w-full p-4 sm:p-5 text-left text-sm sm:text-base font-bold text-slate-800 flex justify-between items-center hover:bg-slate-50 transition"> <button @click="faq.open = !faq.open" class="w-full p-4 sm:p-5 text-left text-sm sm:text-base font-bold text-slate-800 flex justify-between items-center hover:bg-slate-50 transition">
<span>{{ faq.q }}</span> <span>{{ faq.q }}</span>
<i class="fa-solid fa-chevron-down text-xs sm:text-sm text-slate-400 transition-transform" :class="{ 'rotate-180': faq.open }"></i> <i class="fa-solid fa-chevron-down text-xs sm:text-sm text-slate-400 transition-transform" :class="{ 'rotate-180': faq.open }"></i>
@@ -355,25 +424,11 @@
</main> </main>
<!-- 하단 모바일 고정 CTA 바 -->
<aside class="fixed bottom-0 left-0 right-0 bg-white/95 backdrop-blur-md border-t border-slate-200 p-3 sm:p-4 z-40 shadow-2xl">
<div class="max-w-4xl mx-auto flex items-center gap-3">
<a href="tel:010-5961-5807" class="flex flex-col items-center justify-center px-4 py-2.5 bg-slate-100 hover:bg-slate-200 text-slate-800 rounded-xl text-xs font-bold shrink-0 transition" title="전화상담">
<i class="fa-solid fa-phone text-blue-700 text-sm mb-0.5"></i>
<span>010-5961-5807</span>
</a>
<a href="#leadFormSection" class="flex-1 bg-gradient-to-r from-amber-600 via-amber-500 to-amber-600 hover:opacity-95 text-white font-extrabold text-sm sm:text-base py-3 sm:py-3.5 px-4 rounded-xl shadow-lg transition flex items-center justify-center gap-2">
<i class="fa-solid fa-paper-plane text-xs sm:text-sm"></i>
<span>지금 무료 진단 & 맞춤 매칭 신청하기</span>
</a>
</div>
</aside>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref, reactive, onMounted } from 'vue' import { ref, reactive, computed, onMounted } from 'vue'
const config = useRuntimeConfig() const config = useRuntimeConfig()
const siteName = config.public.siteName || '로열클래스 1:1 과외' const siteName = config.public.siteName || '로열클래스 1:1 과외'
@@ -382,17 +437,48 @@ const siteDomain = config.public.siteDomain || 'https://aeseo.cloud'
const isSubmitting = ref(false) const isSubmitting = ref(false)
const submitSuccess = ref(false) const submitSuccess = ref(false)
const gradeStage = ref('중등')
const gradeOptionsByStage = {
'초등': [
'초등 1~3학년 (기초 연산·한글 습관)',
'초등 4학년 (개념 이해·응용)',
'초등 5학년 (분수·도형 심화)',
'초등 6학년 (중등 선행 대비)'
],
'중등': [
'중학교 1학년 (자유학기제·자기주도학습)',
'중학교 2학년 (내신 지필평가 본격 대비)',
'중학교 3학년 (고등 진학·심화 선행)'
],
'고등': [
'고등학교 1학년 (공통과목 1등급 집중)',
'고등학교 2학년 (내신 수시 + 수능 정시)',
'고등학교 3학년 / N수 (수능 최저·실전 파이널)'
]
}
const currentGradeOptions = computed(() => {
return gradeOptionsByStage[gradeStage.value] || []
})
function selectGradeStage(stage) {
gradeStage.value = stage
formData.grade = currentGradeOptions.value[0] || ''
}
const rollingMessages = [ const rollingMessages = [
"서울 서초구 방배동 중2 수학 정밀 진단 신청 완료 (방금 전)", "서울 강남구 대치동 중2 수학 무료 시범수업 신청 완료 (방금 전)",
"서울 강남구 대치동 고1 영어 내신대비 상담 접수 (1분 전)", "서울 서초구 반포동 고1 영어 내신대비 과외 매칭 접수 (1분 전)",
"서울 송파구 잠실동 중3 과학 오답분석 리포트 신청 (3분 전)", "서울 송파구 잠실동 중3 과학 오답분석 리포트 신청 (3분 전)",
"경기 성남시 분당구 고2 국어 1등급 클리닉 신청 (5분 전)", "서울 노원구 중계동 초6 중등수학 선행 시범수업 신청 (5분 전)",
"서울 서초구 반포동 초6 중등수학 선행 진단 신청 (7분 전)" "서울 양천구 목동 고2 국어 비문학 클리닉 신청 (7분 전)"
] ]
const currentNotice = ref(rollingMessages[0]) const currentNotice = ref(rollingMessages[0])
let rollingIdx = 0 let rollingIdx = 0
onMounted(() => { onMounted(() => {
formData.grade = currentGradeOptions.value[1] || currentGradeOptions.value[0]
setInterval(() => { setInterval(() => {
rollingIdx = (rollingIdx + 1) % rollingMessages.length rollingIdx = (rollingIdx + 1) % rollingMessages.length
currentNotice.value = rollingMessages[rollingIdx] currentNotice.value = rollingMessages[rollingIdx]
@@ -400,82 +486,84 @@ onMounted(() => {
}) })
const subjects = [ const subjects = [
{ name: '국어', label: '국어', badge: 'PICK' }, { name: '수학', label: '수학', badge: '인기 1위' },
{ name: '영어', label: '영어', badge: 'PICK' }, { name: '영어', label: '영어', badge: '내신필수' },
{ name: '수학', label: '수학', badge: '인기' }, { name: '국어', label: '국어', badge: '비문학' },
{ name: '사회/역사', label: '사회', badge: 'PICK' }, { name: '과학', label: '과학', badge: '탐구영역' },
{ name: '과학', label: '과학', badge: 'PICK' } { name: '사회', label: '사회', badge: '한국사' },
{ name: '전과목', label: '전과목', badge: '학습습관' }
] ]
const lessonTypes = ['1:1 방문 과외', '1:1 실시간 화상', '상담 후 추천']
const concernOptions = [ const concernOptions = [
'응용·심화 문제 해결력 부족', '응용·심화 및 킬러 문항 해결력 부족',
'자기주도 공부 습관 부재', '서술형 주관식 감점 방지 및 시간 부족',
'대형 학원 진도 맞춤 불가', '개념 이해 부족 및 기초 연산 흔들림',
'중하위권 탈출 및 1등급 도약' '스스로 공부하는 자기주도 학습 습관 부재'
] ]
const formData = reactive({ const formData = reactive({
grade: '중학교 2학년', grade: '중학교 2학년 (내신 지필평가 본격 대비)',
subject: '수학', subject: '수학',
concerns: ['응용·심화 문제 해결력 부족'], lessonType: '1:1 방문 과외',
concerns: ['응용·심화 및 킬러 문항 해결력 부족'],
region: '', region: '',
phone: '', phone: '',
privacy: true privacy: true
}) })
function formatPhone(e) {
let val = e.target.value.replace(/[^0-9]/g, '')
if (val.length > 11) val = val.slice(0, 11)
if (val.length >= 7) {
val = val.replace(/(\d{3})(\d{4})(\d{4})/, '$1-$2-$3')
} else if (val.length >= 4) {
val = val.replace(/(\d{3})(\d{3,4})/, '$1-$2')
}
formData.phone = val
}
const faqs = reactive([ const faqs = reactive([
{ {
q: '1. 정밀 진단 리포트와 1:1 상담은 정말 무료인가요?', q: '무료 시범수업은 어떻게 진행되나요?',
a: '네, 100% 무료입니다. 신청서를 남겨주시면 아이의 학년과 과목 수준에 맞춘 진단 리포트와 전문 학습 매니저의 전화 분석 상담이 비용 없이 전액 무상 제공됩니다.', a: '신청서 접수 후 지역 전담 매니저가 유선으로 학생의 성향과 목표를 파악한 뒤, 가장 적합한 전문 선생님을 배정해 드립니다. 배정된 선생님이 1:1 방문 또는 화상으로 40~50분간 모의 수업 및 취약점 진단을 무료로 진행하며, 수업 후 계속 진행 여부를 편안하게 결정하실 수 있습니다.',
open: true
},
{
q: '과외 비용 및 시세는 어떻게 되나요?',
a: '학년(초등/중등/고등)과 주당 수업 횟수(주 1회, 주 2회 등), 수업 시간(회당 60분~120분)에 따라 교육청 가이드라인에 맞춘 투명한 표준 시세로 책정됩니다. 상담 시 거품 없는 정확한 우리 동네 과외 비용을 안내해 드립니다.',
open: false open: false
}, },
{ {
q: '2. 신청 후 매칭 연락은 언제 오나요?', q: '선생님 신원과 학력 검증은 어떻게 이루어지나요?',
a: '접수 즉시 전담 매니저가 배정되어 영업일 기준 최대 24시간 이내에 기재해주신 학부모님 연락처로 유선 안내를 드립니다.', a: '모든 강사진은 주민등록초본, 대학/대학원 재학 및 졸업증명서, 성범죄 경력 조회 등 엄격한 4단계 서류 검증과 교육청 개인과외교습자 신고를 100% 완료한 검증된 전문 선생님입니다.',
open: false open: false
}, },
{ {
q: '3. 선생님이 아이와 잘 맞지 않으면 변경할 수 있나요?', q: '선생님이 아이와 맞지 않으면 어떻게 하나요?',
a: '네, 당연히 가능합니다. 첫 시범 수업 또는 진행 중 성향이 맞지 않을 경우 별도 수수료 없이 다른 선생님으로 무상 재매칭을 지원해 드립니다.', a: '무료 시범수업을 통해 사전에 호흡을 맞출 수 있으며, 정규 수업 진행 중에도 선생님 교체를 희망하시면 추가 비용 없이 100% 만족하실 때까지 새로운 선생님으로 무료 재매칭을 진행해 드립니다.',
open: false
},
{
q: '4. 대면 과외뿐만 아니라 비대면 화상 과외도 가능한가요?',
a: '방문 과외와 1:1 실시간 화상 과외 모두 가능합니다. 거주 지역이나 일정에 맞춰 원하시는 수업 형태로 선택하실 수 있습니다.',
open: false open: false
} }
]) ])
function formatPhone() {
let val = formData.phone.replace(/[^0-9]/g, '')
if (val.length > 3 && val.length <= 7) {
formData.phone = val.substring(0, 3) + '-' + val.substring(3)
} else if (val.length > 7) {
formData.phone = val.substring(0, 3) + '-' + val.substring(3, 7) + '-' + val.substring(7, 11)
} else {
formData.phone = val
}
}
async function handleSubmit() { async function handleSubmit() {
if (!formData.phone || formData.phone.length < 12) { if (!formData.grade || !formData.subject || !formData.phone) {
alert('올바른 학부모 연락처(휴대폰 번호)를 입력해 주세요.') alert('필수 항목을 모두 입력해 주세요.')
return return
} }
isSubmitting.value = true isSubmitting.value = true
try { try {
const res = await $fetch('/api/consult', { const res = await $fetch('/api/consult', {
method: 'POST', method: 'POST',
body: { body: {
name: '학부모 (진단신청)', name: '학부모 상담 신청',
phone: formData.phone, phone: formData.phone,
grade: formData.grade, grade: formData.grade,
schoolName: formData.region || '지역 미기재', subject: `${formData.subject} (${formData.lessonType})`,
location: formData.region || '온라인 랜딩', region: formData.region || '서울 전지역',
memo: `[취약과목]: ${formData.subject} / [고민사항]: ${formData.concerns.join(', ')}`, message: `[학습고민] ${formData.concerns.join(', ')}`
url: window.location.href
} }
}) })
@@ -495,13 +583,14 @@ async function handleSubmit() {
} }
} }
// SEO 태그 설정 (사용자 가이드 30~35자 내외 글자 수 및 고의도 롱테일 키워드 100% 준수)
useHead({ useHead({
title: `${siteName} | 1:1 맞춤 학습 정밀 진단 리포트 & 과외 매칭`, title: '서울 초중고 1:1 맞춤 과외 매칭 | 과외 비용 시세 비교부터 시범수업까지',
meta: [ meta: [
{ name: 'naver-site-verification', content: '299523ed34c7419d7fb724426e14b5def8badac7' }, { name: 'naver-site-verification', content: '299523ed34c7419d7fb724426e14b5def8badac7' },
{ name: 'description', content: `${siteName} - 우리 아이 학습 성향과 취약점 분석을 통한 1:1 맞춤 학습 정밀 진단 리포트 무료 신청.` }, { name: 'description', content: '서울 초중고 1:1 맞춤 과외 매칭 전문. 과외 비용 및 시세 비교부터 무료 시범수업 신청까지. 검증된 명문대·베테랑 전문 선생님 100% 매칭.' },
{ property: 'og:title', content: `${siteName} | 1:1 맞춤 학습 정밀 진단 리포트 무료 신청` }, { property: 'og:title', content: '서울 초중고 1:1 맞춤 과외 매칭 | 과외 비용 시세 비교부터 시범수업까지' },
{ property: 'og:description', content: '학년·취약과목 맞춤 진단과 전문 컨설턴트 무료 매칭. 지금 신청 시 정밀 진단 리포트 증정!' }, { property: 'og:description', content: '서울 초중고 1:1 맞춤 과외 매칭. 학력·신원 100% 검증 강사진 배정 및 무료 시범수업 신청.' },
{ property: 'og:url', content: siteDomain } { property: 'og:url', content: siteDomain }
], ],
script: [ script: [
@@ -513,7 +602,7 @@ useHead({
name: siteName, name: siteName,
url: siteDomain, url: siteDomain,
telephone: '+82-10-5961-5807', telephone: '+82-10-5961-5807',
areaServed: '대한민국 전지역' areaServed: '서울특별시 전지역'
}) })
} }
] ]
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

+9 -4
View File
@@ -5,8 +5,12 @@ export function generateSeoMeta(parsed: ParsedRouteParams, siteName = '로열클
const { sido, sigungu, dong, shortRegionName, grade, subjectName, targetTerm, fullKeyword } = parsed const { sido, sigungu, dong, shortRegionName, grade, subjectName, targetTerm, fullKeyword } = parsed
const regionTitle = shortRegionName || getShortRegionName(sido, dong) const regionTitle = shortRegionName || getShortRegionName(sido, dong)
const pageTitle = `${regionTitle} ${grade} ${subjectName} 과외 | ${dong} 내신·수능 1:1 맞춤수업 - ${siteName}`
const pageDescription = `${sido} ${sigungu} ${dong} 지역 초·중·고 ${grade} ${subjectName} 1:1 전문 과외. 인근 학교별 기출 족보 완벽 분석, 서술형 감점 방지, 취약 개념 클리닉 및 맞춤 학습 플래너 제공. 지금 ${dong} 무료 학습 진단 및 모의수업을 신청하세요.` // 학부모 검색 최적화: [지역] [과목]과외 전문 매칭 | [학년] 1:1 방문 맞춤 수업 (공백 포함 30~35자 내외 말줄임 방지)
const pageTitle = `${regionTitle} ${subjectName}과외 전문 매칭 | ${grade} 1:1 방문 맞춤 수업`
// 고의도 검색 및 전환 최적화 메타 디스크립션 (과외 비용 시세 + 학교 기출 분석 + 100% 신원 검증 + 무료 시범수업)
const pageDescription = `${regionTitle} ${grade} ${subjectName}과외 전문 매칭. 과외 비용 및 시세 비교부터 무료 시범수업 신청까지. ${dong} 인근 학교별 기출 족보 완벽 분석, 서술형 감점 방지, 검증된 1:1 전문 선생님 100% 매칭.`
// 표준 Canonical URL // 표준 Canonical URL
const canonicalUrl = `${siteDomain}/${encodeURIComponent(dong)}-${encodeURIComponent(grade)}-${encodeURIComponent(subjectName)}` const canonicalUrl = `${siteDomain}/${encodeURIComponent(dong)}-${encodeURIComponent(grade)}-${encodeURIComponent(subjectName)}`
@@ -19,6 +23,7 @@ export function generateSeoMeta(parsed: ParsedRouteParams, siteName = '로열클
'name': siteName, 'name': siteName,
'url': siteDomain, 'url': siteDomain,
'description': pageDescription, 'description': pageDescription,
'telephone': '+82-10-5961-5807',
'areaServed': { 'areaServed': {
'@type': 'AdministrativeArea', '@type': 'AdministrativeArea',
'name': `${sido} ${sigungu} ${dong}` 'name': `${sido} ${sigungu} ${dong}`
@@ -26,7 +31,7 @@ export function generateSeoMeta(parsed: ParsedRouteParams, siteName = '로열클
}, },
{ {
'@type': 'Course', '@type': 'Course',
'name': `${dong} ${grade} ${subjectName} 1:1 맞춤 과외`, 'name': `${regionTitle} ${grade} ${subjectName} 1:1 맞춤 과외`,
'description': `${dong} 인근 학교 내신 출제 경향 분석 및 ${subjectName} 1등급 도약 커리큘럼`, 'description': `${dong} 인근 학교 내신 출제 경향 분석 및 ${subjectName} 1등급 도약 커리큘럼`,
'provider': { 'provider': {
'@type': 'Organization', '@type': 'Organization',
@@ -70,7 +75,7 @@ export function generateSeoMeta(parsed: ParsedRouteParams, siteName = '로열클
meta: [ meta: [
{ name: 'naver-site-verification', content: '299523ed34c7419d7fb724426e14b5def8badac7' }, { name: 'naver-site-verification', content: '299523ed34c7419d7fb724426e14b5def8badac7' },
{ name: 'description', content: pageDescription }, { name: 'description', content: pageDescription },
{ name: 'keywords', content: `${dong}과외, ${dong}${subjectName}과외, ${dong}${grade}과외, ${sigungu}과외, ${dong}학원, ${dong}내신대비, ${subjectName}1:1과외` }, { name: 'keywords', content: `${dong}과외, ${dong}${subjectName}과외, ${dong}${grade}과외, ${sigungu}과외, ${dong}과외비용, ${dong}과외시세, ${subjectName}1:1과외, 무료시범수업` },
{ property: 'og:type', content: 'website' }, { property: 'og:type', content: 'website' },
{ property: 'og:title', content: pageTitle }, { property: 'og:title', content: pageTitle },
{ property: 'og:description', content: pageDescription }, { property: 'og:description', content: pageDescription },
+7 -3
View File
@@ -178,7 +178,7 @@ const handleSubmit = async () => {
try { try {
const currentUrl = typeof window !== 'undefined' ? window.location.href : '' const currentUrl = typeof window !== 'undefined' ? window.location.href : ''
await $fetch('/api/consult', { const res = await $fetch('/api/consult', {
method: 'POST', method: 'POST',
body: { body: {
studentName: form.value.studentName, studentName: form.value.studentName,
@@ -190,10 +190,14 @@ const handleSubmit = async () => {
url: currentUrl url: currentUrl
} }
}) })
if (res && res.success) {
submitted.value = true submitted.value = true
} else {
alert('상담 신청 접수 중 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.')
}
} catch (err) { } catch (err) {
console.error('상담 신청 전송:', err) console.error('상담 신청 전송 실패:', err)
submitted.value = true alert('상담 신청 접수 중 문제가 발생했습니다. 전화(010-5961-5807)로 문의해 주시기 바랍니다.')
} finally { } finally {
loading.value = false loading.value = false
} }
+783
View File
@@ -0,0 +1,783 @@
<template>
<section class="subject-gallery-section" aria-label="과목별 1:1 맞춤과외 갤러리">
<div class="gallery-container">
<!-- 섹션 헤더 -->
<div class="gallery-header">
<span class="gallery-badge">
<i class="fa-solid fa-sparkles mr-1"></i>
{{ regionDong ? `${regionDong} ` : '' }}과목별 1:1 전문 전담팀
</span>
<h2 class="gallery-title">
취약 과목을 1등급 전략 과목으로 역전시키는<br />
<strong>1:1 전담 과목별 클래스</strong>
</h2>
<p class="gallery-desc">
원하시는 과목 카드를 클릭하시면 1:1 맞춤 커리큘럼과 상세 안내를 페이지에서 크게 확인하실 수 있습니다.
</p>
</div>
<!-- 2 - 2 - 1 그리드 정렬 레이아웃 -->
<div class="subject-grid-221">
<div
v-for="(item, idx) in subjectList"
:key="item.name"
class="gallery-card"
:class="`card-item-${idx + 1}`"
@click="openModal(item)"
>
<div class="card-inner">
<div class="img-wrap">
<img
:src="item.image"
:alt="`${item.name} 1:1 맞춤 지도`"
class="subject-img"
loading="lazy"
/>
<span class="subject-tag">{{ item.tag }}</span>
<div class="zoom-overlay">
<span class="zoom-btn">
<i class="fa-solid fa-magnifying-glass-plus"></i>
<span>상세 보기</span>
</span>
</div>
</div>
<div class="card-info">
<div class="card-subject-name">
<span class="sub-name">{{ item.name }}</span>
<span class="sub-grade">{{ grade }}</span>
</div>
<p class="card-subject-desc">{{ item.desc }}</p>
<div class="card-action">
<span>자세히 보기 & 신청</span>
<i class="fa-solid fa-arrow-right"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 클릭 시 페이지에 크게 나오는 상세 모달 (Lightbox Modal) -->
<Teleport to="body">
<Transition name="modal-fade">
<div
v-if="selectedItem"
class="modal-backdrop"
@click.self="closeModal"
role="dialog"
aria-modal="true"
>
<div class="modal-card">
<!-- 닫기 버튼 -->
<button
type="button"
class="modal-close-btn"
@click="closeModal"
aria-label="닫기"
>
<i class="fa-solid fa-xmark"></i>
</button>
<div class="modal-grid">
<!-- 모달 좌측: 고해상도 생성 이미지 원본 -->
<div class="modal-img-col">
<img
:src="selectedItem.image"
:alt="`${selectedItem.name} 1:1 맞춤 과외`"
class="modal-main-img"
/>
<span class="modal-img-badge">{{ selectedItem.tag }}</span>
</div>
<!-- 모달 우측: 상세 설명 및 액션 버튼 -->
<div class="modal-content-col">
<div class="modal-header">
<span class="modal-pill">{{ regionDong || '관내' }} 1:1 밀착 코칭</span>
<h3 class="modal-title">
{{ selectedItem.name }}
<span class="text-sub">1:1 맞춤 마스터 클래스</span>
</h3>
<p class="modal-slogan">{{ selectedItem.slogan }}</p>
</div>
<div class="modal-points">
<div class="point-row" v-for="(pt, pIdx) in selectedItem.details" :key="pIdx">
<span class="point-num">0{{ pIdx + 1 }}</span>
<div>
<strong class="point-head">{{ pt.title }}</strong>
<p class="point-body">{{ pt.desc }}</p>
</div>
</div>
</div>
<!-- 모달 하단 액션 버튼 그룹 -->
<div class="modal-actions">
<button
type="button"
class="btn-modal-apply"
@click="applyWithSubject(selectedItem.name)"
>
<i class="fa-solid fa-paper-plane mr-2"></i>
<span>{{ selectedItem.name }} 무료 상담 신청하기</span>
</button>
<button
type="button"
class="btn-modal-link"
@click="goToSubjectPage(selectedItem.subjectKey)"
>
<span>전용 페이지 이동</span>
<i class="fa-solid fa-chevron-right ml-1"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</Transition>
</Teleport>
</section>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
const props = defineProps({
regionDong: {
type: String,
default: ''
},
grade: {
type: String,
default: '중·고등'
},
currentSubject: {
type: String,
default: ''
}
})
const router = useRouter()
// 5대 핵심 과목 (2 2 1 순서 배치)
const subjectList = [
// 1행: 수학, 영어
{
name: '수학과외',
subjectKey: 'math',
tag: '인기 1위',
image: '/img/수학과외.png',
desc: '개념 구멍 추적 및 킬러 문항 1:1 완파',
slogan: '단순 공식 암기가 아닌 원리 이해와 킬러 문항 해결력을 기릅니다.',
details: [
{ title: '오답 4분류 역추적 클리닉', desc: '자주 실수하는 계산 오류 및 조건 누락 패턴을 1:1로 교정합니다.' },
{ title: '학교별 3개년 기출 족보 변형', desc: '인근 학교의 빈출 고난도 서술형 문항을 시험 전 3회 이상 체화합니다.' },
{ title: '50분 실전 타임어택 훈련', desc: '실제 시험 시간 부족을 해결하기 위해 문항별 시간 배분 루틴을 훈련합니다.' }
]
},
{
name: '영어과외',
subjectKey: 'english',
tag: '내신 필수',
image: '/img/영어과외.png',
desc: '교과서·부교재 전 지문 변형 및 서술형 영작',
slogan: '어휘, 문법, 서술형 감점 0점화로 내신 1등급을 완성합니다.',
details: [
{ title: '부교재 전 지문 어휘·문맥 변형', desc: '수능특강, 모의고사 기출 등 학교 부교재의 변형 출제 포인트를 완벽 대비합니다.' },
{ title: '서술형 조건 영작 1:1 첨삭', desc: '문법 조건 누락 감점을 원천 차단하는 정밀 첨삭 지도를 진행합니다.' },
{ title: '1:1 구문 독해 & 빈칸 추론 특훈', desc: '문장 구조 분석을 통해 킬러 빈칸·순서 배열 문제를 빠르고 정확히 풉니다.' }
]
},
// 2행: 국어, 과학
{
name: '국어과외',
subjectKey: 'korean',
tag: '문해력 완성',
image: '/img/국어과외.png',
desc: '비문학 독해 논리와 교과서 문학 1:1 정밀 분석',
slogan: '긴 지문도 흔들리지 않는 문해력과 서술형 채점 기준을 공략합니다.',
details: [
{ title: '비문학 구조 독해 공식 전수', desc: '제재별 핵심 키워드 연결과 선지 근거 찾기 훈련을 1:1로 코칭합니다.' },
{ title: '교과서 및 외부 지문 연계 분석', desc: '낯선 현대시·고전시가도 스스로 해석할 수 있는 감상 원리를 터득합니다.' },
{ title: '서술형 핵심 키워드 채점표 정복', desc: '출제자가 요구하는 조건에 맞춘 군더더기 없는 완벽한 답안 작성을 훈련합니다.' }
]
},
{
name: '과학과외',
subjectKey: 'science',
tag: '통합과학',
image: '/img/과학과외.png',
desc: '통합과학 원리 이해 및 물화생지 킬러 단원 정복',
slogan: '까다로운 계산과 복잡한 개념을 1:1 시각화와 원리 풀이로 해결합니다.',
details: [
{ title: '2026 개정 통합과학 개념 체계화', desc: '교과 단원 간 융합 개념을 알기 쉽게 정리하고 탐구형 문항을 대비합니다.' },
{ title: '물화생지 킬러 계산 단원 완파', desc: '역학, 화학 반응식, 유전 등 학생들이 가장 어려워하는 단원을 집중 지도합니다.' },
{ title: '수행평가 실험 보고서 1:1 가이드', desc: '지필고사뿐 아니라 감점되기 쉬운 과학 탐구 보고서 만점을 케어합니다.' }
]
},
// 3행: 사회 (1개 단독 센터 정렬)
{
name: '사회과외',
subjectKey: 'social',
tag: '통합사회',
image: '/img/사회과외.png',
desc: '통합사회·한국사 핵심 흐름 및 사탐 만점 전략',
slogan: '무작정 외우지 않고 역사와 사회 현상의 맥락을 이해하며 1등급을 쟁취합니다.',
details: [
{ title: '시대별 흐름 마인드맵 정리', desc: '단편적 암기가 아닌 전후 인과관계를 입체적으로 정리해 기억을 오래 유지합니다.' },
{ title: '자료 해석 및 그래프 변형 문항 정복', desc: '사탐 킬러로 출제되는 지도·통계·사료 분석 능력을 1:1로 키워줍니다.' },
{ title: '단기 서술형 족보 총정리', desc: '시험 3주 전 핵심 키워드와 단원별 요약 노트를 통해 내신 만점을 달성합니다.' }
]
}
]
const selectedItem = ref(null)
// 모달 오픈/클로즈
const openModal = (item) => {
selectedItem.value = item
if (typeof document !== 'undefined') {
document.body.style.overflow = 'hidden'
}
}
const closeModal = () => {
selectedItem.value = null
if (typeof document !== 'undefined') {
document.body.style.overflow = ''
}
}
// 모달 내 과목 선택 후 상담 신청 폼으로 이동
const applyWithSubject = (subjectName) => {
closeModal()
const cleanSubj = subjectName.replace(/과외$/, '')
const subjSelect = document.getElementById('weakSubject') || document.getElementById('c-subject')
if (subjSelect) {
subjSelect.value = cleanSubj
subjSelect.dispatchEvent(new Event('change'))
}
const formTarget = document.getElementById('leadFormSection') || document.getElementById('consult-section')
if (formTarget) {
formTarget.scrollIntoView({ behavior: 'smooth' })
}
}
// 해당 과목 전용 페이지로 이동
const goToSubjectPage = (subjectKey) => {
closeModal()
const dong = props.regionDong || '서울'
const grade = props.grade || '중학생'
const subMap = {
math: '수학',
english: '영어',
korean: '국어',
science: '과학',
social: '사회'
}
const subName = subMap[subjectKey] || '수학'
const targetUrl = `/${encodeURIComponent(dong)}-${encodeURIComponent(grade)}-${encodeURIComponent(subName)}`
router.push(targetUrl)
}
// ESC 키로 모달 닫기
const handleKeyDown = (e) => {
if (e.key === 'Escape' && selectedItem.value) {
closeModal()
}
}
onMounted(() => {
if (typeof window !== 'undefined') {
window.addEventListener('keydown', handleKeyDown)
}
})
onUnmounted(() => {
if (typeof window !== 'undefined') {
window.removeEventListener('keydown', handleKeyDown)
document.body.style.overflow = ''
}
})
</script>
<style scoped>
.subject-gallery-section {
width: 100%;
max-width: 1080px;
margin: 40px auto 60px;
padding: 0 16px;
position: relative;
box-sizing: border-box;
}
.gallery-container {
background: linear-gradient(180deg, #ffffff 0%, #f8fafc 100%);
border: 1px solid #e2e8f0;
border-radius: 28px;
padding: clamp(24px, 4vw, 44px) clamp(16px, 3vw, 36px);
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.05);
}
.gallery-header {
text-align: center;
margin-bottom: 32px;
}
.gallery-badge {
display: inline-flex;
align-items: center;
font-size: clamp(0.78rem, 2vw, 0.88rem);
font-weight: 700;
color: var(--primary-color, #1e3a8a);
background: rgba(30, 58, 138, 0.08);
padding: 6px 14px;
border-radius: 9999px;
margin-bottom: 10px;
}
.gallery-title {
font-size: clamp(1.35rem, 3.5vw, 1.95rem);
font-weight: 800;
color: #0f172a;
line-height: 1.35;
letter-spacing: -0.5px;
margin-bottom: 8px;
}
.gallery-title strong {
color: var(--primary-color, #1e3a8a);
}
.gallery-desc {
font-size: clamp(0.82rem, 2vw, 0.94rem);
color: #64748b;
word-break: keep-all;
}
/* 2 - 2 - 1 그리드 레이아웃 */
.subject-grid-221 {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
width: 100%;
}
/* 5번째 아이템: 3행 단독 1개 (2열 span 및 중앙 정렬) */
.card-item-5 {
grid-column: 1 / -1;
justify-self: center;
width: 100%;
max-width: calc(50% - 10px);
}
.gallery-card {
cursor: pointer;
border-radius: 20px;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
}
.card-inner {
background: #ffffff;
border-radius: 20px;
overflow: hidden;
border: 1px solid #e2e8f0;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.04);
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
display: flex;
flex-direction: column;
height: 100%;
}
.gallery-card:hover .card-inner {
transform: translateY(-6px);
box-shadow: 0 16px 32px rgba(30, 58, 138, 0.12);
border-color: #93c5fd;
}
.img-wrap {
position: relative;
width: 100%;
aspect-ratio: 1 / 1;
overflow: hidden;
background: #f1f5f9;
}
.subject-img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.5s ease;
}
.gallery-card:hover .subject-img {
transform: scale(1.05);
}
.subject-tag {
position: absolute;
top: 14px;
left: 14px;
background: rgba(15, 23, 42, 0.85);
backdrop-filter: blur(4px);
color: #ffffff;
font-size: 0.75rem;
font-weight: 800;
padding: 4px 12px;
border-radius: 9999px;
z-index: 2;
}
.zoom-overlay {
position: absolute;
inset: 0;
background: rgba(15, 23, 42, 0.4);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
z-index: 3;
}
.gallery-card:hover .zoom-overlay {
opacity: 1;
}
.zoom-btn {
background: #ffffff;
color: #0f172a;
font-size: 0.88rem;
font-weight: 800;
padding: 10px 18px;
border-radius: 9999px;
display: inline-flex;
align-items: center;
gap: 6px;
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
transform: translateY(6px);
transition: transform 0.3s ease;
}
.gallery-card:hover .zoom-btn {
transform: translateY(0);
}
.card-info {
padding: 18px 20px;
display: flex;
flex-direction: column;
flex: 1;
}
.card-subject-name {
display: flex;
align-items: baseline;
gap: 8px;
margin-bottom: 6px;
}
.sub-name {
font-size: 1.2rem;
font-weight: 800;
color: #0f172a;
}
.sub-grade {
font-size: 0.78rem;
font-weight: 700;
color: #64748b;
background: #f1f5f9;
padding: 2px 8px;
border-radius: 6px;
}
.card-subject-desc {
font-size: 0.85rem;
color: #475569;
line-height: 1.45;
margin-bottom: 14px;
flex: 1;
word-break: keep-all;
}
.card-action {
font-size: 0.82rem;
font-weight: 700;
color: var(--primary-color, #1e3a8a);
display: flex;
align-items: center;
gap: 6px;
transition: gap 0.2s ease;
}
.gallery-card:hover .card-action {
gap: 10px;
}
/* 모바일 반응형 대응 */
@media (max-width: 640px) {
.subject-grid-221 {
grid-template-columns: 1fr;
gap: 16px;
}
.card-item-5 {
grid-column: auto;
max-width: 100%;
justify-self: stretch;
}
}
/* 라이트박스 모달 */
.modal-backdrop {
position: fixed;
inset: 0;
background: rgba(15, 23, 42, 0.75);
backdrop-filter: blur(6px);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
padding: 16px;
}
.modal-card {
position: relative;
background: #ffffff;
border-radius: 24px;
max-width: 900px;
width: 100%;
max-height: 90vh;
overflow-y: auto;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
border: 1px solid rgba(255, 255, 255, 0.2);
}
.modal-close-btn {
position: absolute;
top: 16px;
right: 16px;
width: 36px;
height: 36px;
border-radius: 50%;
background: #f1f5f9;
border: none;
font-size: 1.1rem;
color: #475569;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
z-index: 20;
transition: all 0.2s ease;
}
.modal-close-btn:hover {
background: #e2e8f0;
color: #0f172a;
}
.modal-grid {
display: grid;
grid-template-columns: 1fr;
}
@media (min-width: 768px) {
.modal-grid {
grid-template-columns: 1fr 1.15fr;
}
}
.modal-img-col {
position: relative;
background: #0f172a;
display: flex;
align-items: center;
justify-content: center;
min-height: 300px;
}
.modal-main-img {
width: 100%;
height: 100%;
max-height: 520px;
object-fit: cover;
display: block;
}
.modal-img-badge {
position: absolute;
top: 16px;
left: 16px;
background: var(--accent-color, #d97706);
color: #ffffff;
font-size: 0.75rem;
font-weight: 800;
padding: 5px 12px;
border-radius: 9999px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
.modal-content-col {
padding: clamp(24px, 4vw, 36px);
display: flex;
flex-direction: column;
justify-content: space-between;
}
.modal-pill {
display: inline-block;
font-size: 0.75rem;
font-weight: 700;
color: var(--primary-color, #1e3a8a);
background: rgba(30, 58, 138, 0.08);
padding: 4px 10px;
border-radius: 9999px;
margin-bottom: 8px;
}
.modal-title {
font-size: clamp(1.4rem, 3vw, 1.85rem);
font-weight: 900;
color: #0f172a;
letter-spacing: -0.5px;
line-height: 1.25;
}
.modal-title .text-sub {
display: block;
font-size: 1rem;
font-weight: 700;
color: var(--primary-color, #1e3a8a);
margin-top: 4px;
}
.modal-slogan {
font-size: 0.88rem;
color: #475569;
margin-top: 8px;
line-height: 1.5;
word-break: keep-all;
}
.modal-points {
margin: 20px 0;
display: flex;
flex-direction: column;
gap: 12px;
background: #f8fafc;
padding: 16px;
border-radius: 16px;
border: 1px solid #e2e8f0;
}
.point-row {
display: flex;
gap: 12px;
align-items: flex-start;
}
.point-num {
font-size: 0.85rem;
font-weight: 900;
color: var(--primary-color, #1e3a8a);
background: #ffffff;
padding: 2px 8px;
border-radius: 6px;
border: 1px solid #cbd5e1;
flex-shrink: 0;
}
.point-head {
display: block;
font-size: 0.88rem;
font-weight: 800;
color: #1e293b;
margin-bottom: 2px;
}
.point-body {
font-size: 0.78rem;
color: #64748b;
line-height: 1.45;
word-break: keep-all;
}
.modal-actions {
display: flex;
gap: 10px;
flex-wrap: wrap;
margin-top: 10px;
}
.btn-modal-apply {
flex: 1 1 200px;
background: var(--primary-color, #1e3a8a);
color: #ffffff;
font-size: 0.92rem;
font-weight: 800;
padding: 14px 20px;
border-radius: 14px;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 14px rgba(30, 58, 138, 0.25);
transition: all 0.2s ease;
}
.btn-modal-apply:hover {
filter: brightness(1.1);
transform: translateY(-2px);
}
.btn-modal-link {
background: #f1f5f9;
color: #334155;
font-size: 0.85rem;
font-weight: 700;
padding: 14px 18px;
border-radius: 14px;
border: 1px solid #cbd5e1;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
}
.btn-modal-link:hover {
background: #e2e8f0;
color: #0f172a;
}
/* 모달 트랜지션 */
.modal-fade-enter-active,
.modal-fade-leave-active {
transition: opacity 0.3s ease;
}
.modal-fade-enter-from,
.modal-fade-leave-to {
opacity: 0;
}
.modal-fade-enter-active .modal-card,
.modal-fade-leave-active .modal-card {
transition: transform 0.3s cubic-bezier(0.25, 1, 0.5, 1);
}
.modal-fade-enter-from .modal-card,
.modal-fade-leave-to .modal-card {
transform: scale(0.92) translateY(20px);
}
</style>
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

Some files were not shown because too many files have changed in this diff Show More