diff --git a/frontend/assets/css/main.css b/frontend/assets/css/main.css index ef11ebb..a75c7e9 100644 --- a/frontend/assets/css/main.css +++ b/frontend/assets/css/main.css @@ -30,9 +30,9 @@ box-sizing: border-box; } -html { - scroll-behavior: smooth; -} +/* scroll-behavior: smooth 는 라우트 이동 시 스크롤 복원과 충돌해 + 페이지 진입 시 자동 스크롤 버그를 유발하므로 제거. + (인페이지 부드러운 스크롤은 JS window.scrollTo({behavior:'smooth'}) 로 개별 처리) */ body { background: var(--bg); diff --git a/frontend/assets/images/img-brand.svg b/frontend/assets/images/img-brand.svg new file mode 100644 index 0000000..4453f41 --- /dev/null +++ b/frontend/assets/images/img-brand.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/frontend/assets/images/img-hongkong.svg b/frontend/assets/images/img-hongkong.svg new file mode 100644 index 0000000..c1905be --- /dev/null +++ b/frontend/assets/images/img-hongkong.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/assets/images/img-necklace.png b/frontend/assets/images/img-necklace.png new file mode 100644 index 0000000..0506d23 Binary files /dev/null and b/frontend/assets/images/img-necklace.png differ diff --git a/frontend/assets/images/img-usa.svg b/frontend/assets/images/img-usa.svg new file mode 100644 index 0000000..17c4d53 --- /dev/null +++ b/frontend/assets/images/img-usa.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/assets/images/page1.png b/frontend/assets/images/page1.png new file mode 100644 index 0000000..7b4574d Binary files /dev/null and b/frontend/assets/images/page1.png differ diff --git a/frontend/assets/images/page2.png b/frontend/assets/images/page2.png new file mode 100644 index 0000000..0fa8817 Binary files /dev/null and b/frontend/assets/images/page2.png differ diff --git a/frontend/assets/images/page3-1.png b/frontend/assets/images/page3-1.png new file mode 100644 index 0000000..e518bb2 Binary files /dev/null and b/frontend/assets/images/page3-1.png differ diff --git a/frontend/assets/images/page3.png b/frontend/assets/images/page3.png new file mode 100644 index 0000000..1b20855 Binary files /dev/null and b/frontend/assets/images/page3.png differ diff --git a/frontend/assets/images/page4.png b/frontend/assets/images/page4.png new file mode 100644 index 0000000..738cc94 Binary files /dev/null and b/frontend/assets/images/page4.png differ diff --git a/frontend/assets/images/page5.png b/frontend/assets/images/page5.png new file mode 100644 index 0000000..4eee080 Binary files /dev/null and b/frontend/assets/images/page5.png differ diff --git a/frontend/assets/videos/hero2.mp4 b/frontend/assets/videos/hero2.mp4 new file mode 100644 index 0000000..29d7d79 Binary files /dev/null and b/frontend/assets/videos/hero2.mp4 differ diff --git a/frontend/components/AppHeader.vue b/frontend/components/AppHeader.vue index faaba52..79f33c2 100644 --- a/frontend/components/AppHeader.vue +++ b/frontend/components/AppHeader.vue @@ -15,9 +15,11 @@ withDefaults(defineProps(), { innertab - - 커피챗 신청 - + ← 채용 홈으로 @@ -50,6 +52,27 @@ header { display: block; } +/* 우측 내비게이션 묶음 — 링크 + CTA */ +.nav-actions { + display: flex; + align-items: center; + gap: clamp(1rem, 2.4vw, 1.875rem); /* 16~30px */ +} + +/* 일반 내비게이션 링크 (조직문화 등) */ +.nav-link { + font-size: 0.9375rem; /* 15px */ + font-weight: 600; + color: var(--ink-soft); + white-space: nowrap; + transition: color 0.2s ease; +} + +.nav-link:hover, +.nav-link.router-link-active { + color: var(--ink); +} + .nav-cta { font-size: 0.9375rem; /* 15px */ font-weight: 700; diff --git a/frontend/composables/useSeo.ts b/frontend/composables/useSeo.ts index cbaf75f..a4f999d 100644 --- a/frontend/composables/useSeo.ts +++ b/frontend/composables/useSeo.ts @@ -5,7 +5,8 @@ interface SeoOptions { title: string // 페이지 제목 ( + og:title) description: string // 메타 설명 (검색결과/공유 미리보기) path: string // 라우트 경로 (canonical·og:url 구성), 예: '/', '/coffee-chat' - image?: string // OG 이미지 경로 (기본 /og-image.jpg) + image?: string // OG 이미지 경로 (기본 /og-logo.jpg — 로고 이미지) + keywords?: string // 메타 키워드(쉼표 구분, 선택) noindex?: boolean // 검색 노출 제외 여부 } @@ -14,11 +15,12 @@ export function useSeo(opts: SeoOptions) { // 끝 슬래시 제거 후 절대 URL 구성 const siteUrl = String(config.public.siteUrl || '').replace(/\/$/, '') const url = siteUrl + opts.path - const image = siteUrl + (opts.image || '/og-image.jpg') + const image = siteUrl + (opts.image || '/og-logo.jpg') useSeoMeta({ title: opts.title, description: opts.description, + ...(opts.keywords ? { keywords: opts.keywords } : {}), ogTitle: opts.title, ogDescription: opts.description, ogUrl: url, diff --git a/frontend/nuxt.config.ts b/frontend/nuxt.config.ts index ade0157..34aa551 100644 --- a/frontend/nuxt.config.ts +++ b/frontend/nuxt.config.ts @@ -58,7 +58,7 @@ export default defineNuxtConfig({ }, { rel: 'stylesheet', - href: 'https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Noto+Sans+KR:wght@400;500;700;900&display=swap', + href: 'https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Jua&family=Noto+Sans+KR:wght@400;500;700;900&display=swap', }, ], }, diff --git a/frontend/pages/coffee-chat.vue b/frontend/pages/coffee-chat.vue index 81679f0..7bd5844 100644 --- a/frontend/pages/coffee-chat.vue +++ b/frontend/pages/coffee-chat.vue @@ -2,11 +2,41 @@ // 커피챗 신청 — 클라이언트 검증 + 완료 화면 (원본 바닐라 JS → Vue 반응형 이식) import { reactive, ref, nextTick } from 'vue' +const config = useRuntimeConfig() +const siteUrl = String(config.public.siteUrl || '').replace(/\/$/, '') + useSeo({ title: '커피챗 신청 | 이너탭(innertab)', description: '정식 지원 전에 이너탭 담당자와 가볍게 이야기 나눠보세요. 약 30분 내외, 온·오프라인으로 진행되는 커피챗을 신청할 수 있습니다.', path: '/coffee-chat', + keywords: + '이너탭, innertab, 커피챗, 채용 상담, 커리어 상담, 채용, 면담 신청, 입사 지원, 스타트업 채용', +}) + +// 구조화 데이터(JSON-LD) — 연락/신청 페이지(ContactPage) + 빵부스러기 +useHead({ + script: [ + { + type: 'application/ld+json', + innerHTML: JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'ContactPage', + name: '커피챗 신청 | 이너탭(innertab)', + description: '이너탭 담당자와의 비공식 커피챗(채용 전 면담) 신청 페이지', + url: `${siteUrl}/coffee-chat`, + isPartOf: { '@type': 'WebSite', name: '이너탭 innertab', url: siteUrl }, + about: { '@type': 'Organization', name: '이너탭', alternateName: 'innertab', url: siteUrl }, + breadcrumb: { + '@type': 'BreadcrumbList', + itemListElement: [ + { '@type': 'ListItem', position: 1, name: '홈', item: `${siteUrl}/` }, + { '@type': 'ListItem', position: 2, name: '커피챗', item: `${siteUrl}/coffee-chat` }, + ], + }, + }), + }, + ], }) // 폼 상태 diff --git a/frontend/pages/culture.vue b/frontend/pages/culture.vue new file mode 100644 index 0000000..d3e236a --- /dev/null +++ b/frontend/pages/culture.vue @@ -0,0 +1,1118 @@ +<script setup lang="ts"> +// 조직문화 — 사원증(목걸이) 히어로 + 목표 매출 성장 그래프(스크롤 시 라인 등장 애니메이션) +import imgNecklace from '~/assets/images/img-necklace.png' + +const config = useRuntimeConfig() +const siteUrl = String(config.public.siteUrl || '').replace(/\/$/, '') + +useSeo({ + title: '조직문화 — 투명한 보상·실력 중심 성장·아낌없는 복지 | 이너탭(innertab)', + description: + '이너탭(innertab)의 조직문화를 소개합니다. 투명하고 높은 수준의 보상(성과금 최대 연봉 75%·영업이익 30% 추가 분배), 연차가 아닌 실력으로 승진하는 Level 제도, 유연근무·재택근무·교육비 100% 지원·자유로운 휴가·식대 지원 등 일하기 좋은 환경과 아낌없는 복지로 함께 성장할 동료를 찾습니다.', + path: '/culture', + keywords: + '이너탭, innertab, 조직문화, 기업문화, 스타트업 채용, 복지, 성과급, 보상, 커리어 성장, 유연근무, 재택근무, 교육비 지원, 자유로운 휴가, 수평적 문화, 채용', +}) + +// 구조화 데이터(JSON-LD) — 조직문화(AboutPage) + 빵부스러기(BreadcrumbList) +useHead({ + script: [ + { + type: 'application/ld+json', + innerHTML: JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'AboutPage', + name: '조직문화 | 이너탭(innertab)', + description: + '이너탭(innertab)의 보상·커리어 성장·복지 등 조직문화 소개', + url: `${siteUrl}/culture`, + isPartOf: { '@type': 'WebSite', name: '이너탭 innertab', url: siteUrl }, + about: { '@type': 'Organization', name: '이너탭', alternateName: 'innertab', url: siteUrl }, + breadcrumb: { + '@type': 'BreadcrumbList', + itemListElement: [ + { '@type': 'ListItem', position: 1, name: '홈', item: `${siteUrl}/` }, + { '@type': 'ListItem', position: 2, name: '조직문화', item: `${siteUrl}/culture` }, + ], + }, + }), + }, + ], +}) + +// 복지 — 상단 원형 배지 3개 +interface WelfareBadge { + title: string + sub: string +} +const welfareBadges: WelfareBadge[] = [ + { title: '매주 금요일', sub: '1시간 조기 퇴근' }, + { title: '생일자 5만원', sub: '상당 선물' }, + { title: '개별 성과급', sub: '분기 1회' }, +] + +// 복지 항목 — 이모지 + 2줄 설명 +interface Perk { + icon: string + l1: string + l2: string + desk?: boolean // 책상 — 유니코드 desk 이모지가 없어 인라인 SVG로 표시 +} +const envPerks: Perk[] = [ + { icon: '⏰', l1: '유연근무제', l2: '(9시~10시)' }, + { icon: '💳', l1: '가끔가다 있는 점심 회식', l2: '(feat. 오마카세 & 호텔뷔페)' }, + { icon: '👕', l1: '자유로운 복장', l2: '' }, + { icon: '🙌', l1: '수평적 문화', l2: '(진짜로)' }, + { icon: '', desk: true, l1: '넓은 책상간격', l2: '(의외로 중요)' }, + { icon: '🖥️', l1: '최신형 업무기기', l2: '(Mac or window 택1)' }, +] +const supportPerks: Perk[] = [ + { icon: '📚', l1: '교육비 100% 지원', l2: '(강의, 전자책, 도서등)' }, + { icon: '🏠', l1: '재택근무', l2: '(협의 가능)' }, + { icon: '✈️', l1: '자유로운 휴가', l2: '(연차/월차/반차/반반차)' }, + { icon: '🍽️', l1: '혹시 모를 야근 시', l2: '식대 지원' }, +] + +// 그래프가 화면에 들어오면 라인/포인트 애니메이션 트리거 +const chartEl = ref<HTMLElement | null>(null) +const lineEl = ref<SVGPathElement | null>(null) +const animated = ref(false) + +onMounted(() => { + if (!chartEl.value) return + // 라인 실제 길이를 측정해 stroke-dash 기준값으로 사용(정확한 그리기 애니메이션) + if (lineEl.value) { + const len = lineEl.value.getTotalLength() + lineEl.value.style.setProperty('--len', String(len)) + } + // 모션 최소화 선호 시 애니메이션 없이 최종 상태로 즉시 표시 + if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) { + animated.value = true + return + } + const io = new IntersectionObserver( + (entries) => { + for (const entry of entries) { + if (entry.isIntersecting) { + // 시작 시점을 살짝 늦춤 + window.setTimeout(() => { + animated.value = true + }, 300) + io.disconnect() + break + } + } + }, + { threshold: 0.3 }, + ) + io.observe(chartEl.value) + onUnmounted(() => io.disconnect()) +}) +</script> + +<template> + <div> + <AppHeader variant="home" /> + + <!-- ===================== CULTURE HERO ===================== --> + <section class="culture-hero"> + <div class="hero-inner"> + <!-- 사원증 목걸이 --> + <img + v-reveal:fade + class="badge" + :src="imgNecklace" + alt="이너탭(ITAB) 사원증" + > + <p v-reveal="{ delay: 120 }" class="brand-eyebrow">INNERTAB</p> + <h1 v-reveal="{ delay: 200 }" class="culture-title">Culture</h1> + <p v-reveal="{ delay: 300 }" class="culture-sub"> + 이너탭은 새로운 역사를 써내려갈<br >우리만의 문화를 만들고 있습니다. + </p> + </div> + </section> + + <!-- ===================== 목표 매출 성장 그래프 ===================== --> + <section class="growth-graph"> + <div class="wrap"> + <p v-reveal class="g-eyebrow">2026년 목표 매출</p> + <h2 v-reveal="{ delay: 100 }" class="g-title">150억 기업으로</h2> + <hr v-reveal="{ delay: 160 }" class="g-divider" > + <p v-reveal="{ delay: 220 }" class="g-sub"> + <strong>유능한 팀원</strong>과 <strong>압도적인 커리어</strong>를 지향합니다 + </p> + + <div ref="chartEl" class="chart" :class="{ 'is-animated': animated }"> + <svg + class="chart-svg" + viewBox="0 0 1000 460" + role="img" + aria-label="2023년 창립부터 2028년 목표 1000억까지의 매출 성장 그래프" + > + <defs> + <!-- 끝점 글로우 --> + <filter id="dotGlow" x="-150%" y="-150%" width="400%" height="400%"> + <feGaussianBlur stdDeviation="5" /> + </filter> + <!-- 라인 아래 채움 그라데이션 (위는 진하고 아래로 투명) --> + <linearGradient id="areaFill" x1="0" y1="0" x2="0" y2="1"> + <stop offset="0" stop-color="#6ea8e6" stop-opacity="0.3" /> + <stop offset="1" stop-color="#6ea8e6" stop-opacity="0" /> + </linearGradient> + <!-- 좌→우로 펼쳐지는 reveal 클립 (라인 그리기와 동기화) --> + <clipPath id="areaReveal"> + <rect class="reveal-rect" x="0" y="0" width="1000" height="460" /> + </clipPath> + </defs> + + <!-- 라인 아래 채움 영역 (좌→우로 펼쳐짐) --> + <path + class="area" + clip-path="url(#areaReveal)" + d="M60,388 L280,358 L500,305 L730,230 L940,80 L940,412 L60,412 Z" + /> + + <!-- 각 포인트의 세로 점선 (baseline까지) --> + <path class="dropline" style="transition-delay: 0s" d="M60,388 V412" /> + <path class="dropline" style="transition-delay: 0.4s" d="M280,358 V412" /> + <path class="dropline" style="transition-delay: 0.8s" d="M500,305 V412" /> + <path class="dropline" style="transition-delay: 1.2s" d="M730,230 V412" /> + <path class="dropline" style="transition-delay: 1.6s" d="M940,80 V412" /> + + <!-- 메인 라인 (좌하단→우상단 그려짐) --> + <path + ref="lineEl" + class="line" + d="M60,388 L280,358 L500,305 L730,230 L940,80" + /> + + <!-- 데이터 포인트 --> + <circle class="dot" cx="60" cy="388" r="4.5" style="transition-delay: 0.1s" /> + <circle class="dot" cx="280" cy="358" r="4.5" style="transition-delay: 0.5s" /> + <circle class="dot" cx="500" cy="305" r="4.5" style="transition-delay: 0.9s" /> + <circle class="dot" cx="730" cy="230" r="4.5" style="transition-delay: 1.3s" /> + + <!-- 끝점 (2028) — 빛나는 강조 --> + <circle class="dot-glow" cx="940" cy="80" r="15" filter="url(#dotGlow)" /> + <circle class="dot-ring" cx="940" cy="80" r="9" /> + <circle class="dot-end" cx="940" cy="80" r="5" /> + + <!-- 라벨 (연도 + 값) --> + <text class="lbl" x="60" y="344" text-anchor="middle" style="transition-delay: 0.25s"> + <tspan class="lbl-year" x="60">2023년</tspan> + <tspan class="lbl-val" x="60" dy="20">창립</tspan> + </text> + <text class="lbl" x="280" y="314" text-anchor="middle" style="transition-delay: 0.65s"> + <tspan class="lbl-year" x="280">2024년</tspan> + <tspan class="lbl-val" x="280" dy="20">55억</tspan> + </text> + <text class="lbl" x="500" y="261" text-anchor="middle" style="transition-delay: 1.05s"> + <tspan class="lbl-year" x="500">2026년 목표</tspan> + <tspan class="lbl-val" x="500" dy="20">150억(e)</tspan> + </text> + <text class="lbl" x="730" y="186" text-anchor="middle" style="transition-delay: 1.45s"> + <tspan class="lbl-year" x="730">2027년 목표</tspan> + <tspan class="lbl-val" x="730" dy="20">300억</tspan> + </text> + <text class="lbl" x="940" y="36" text-anchor="end" style="transition-delay: 1.85s"> + <tspan class="lbl-year" x="940">2028년 목표</tspan> + <tspan class="lbl-val lbl-val--hl" x="940" dy="20">1000억+</tspan> + </text> + </svg> + </div> + </div> + </section> + + <!-- ===================== 3가지 약속 인트로 ===================== --> + <section class="promise-intro"> + <span v-reveal class="read-badge">Read This!</span> + <h2 v-reveal="{ delay: 100 }" class="promise-q"> + 이너탭은<br ><strong>3가지</strong>를 약속합니다. + </h2> + <svg class="promise-chevron" viewBox="0 0 24 24" aria-hidden="true"> + <path d="M5 9l7 7 7-7" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> + </svg> + </section> + + <!-- ===================== 첫째 — 보상 약속 / 둘째 — 커리어 성장 ===================== --> + <section class="promise-panel"> + <div class="wrap"> + <div class="panel-inner"> + <!-- 첫째 — 요소별로 화면 진입 시 각각 등장 --> + <h3 v-reveal class="promise-title"> + 첫째,<br ><span class="t-soft">투명하고 높은 수준의</span><br >보상을 약속합니다. + </h3> + <hr class="panel-divider" > + <p v-reveal class="panel-eyebrow">About INNERTAB</p> + <h4 v-reveal="{ delay: 80 }" class="panel-head">말 뿐인 보상은 의미 없습니다.</h4> + <p v-reveal="{ delay: 160 }" class="panel-sub"> + 좋은 결과를 냈다면, 그에 맞는 최고의 보상이<br ><strong>“즉각”</strong> 따라야 한다고 생각합니다. + </p> + <ul class="rule-list"> + <li v-reveal class="rule-card"> + <span class="rule-no">RULE 1</span> + <p class="rule-text">연차나 직급이 아닌, 실제로 해결한 문제가 회사의 성장으로 이어졌다면 보상이 주어집니다.</p> + </li> + <li v-reveal="{ delay: 100 }" class="rule-card"> + <span class="rule-no">RULE 2</span> + <p class="rule-text">성과금은 목표 달성 시 <mark>연봉의 75%까지 지급</mark>됩니다. (LEVEL2 기준, 분기별 지급)</p> + </li> + <li v-reveal="{ delay: 200 }" class="rule-card"> + <span class="rule-no">RULE 3</span> + <p class="rule-text">목표 초과 달성 시, <mark>영업이익의 30% 추가 분배</mark>합니다. (상한 없음)</p> + </li> + </ul> + </div> + </div> + </section> + + <!-- ===================== 둘째 — 커리어 성장(회색) ===================== --> + <section class="promise-second"> + <div class="wrap"> + <div class="panel-inner"> + <h3 v-reveal class="promise-title"> + 둘째,<br >커리어 성장을<br >약속해요. + </h3> + <hr class="panel-divider" > + <div v-reveal="{ delay: 80 }" class="promise-body"> + <p>ITAB은 Level 제도를 운영중이며,<br ><strong>연차가 아닌 실력으로 승진합니다.</strong></p> + <p>업계 3~4년차 수준의 역량을 1년 안에 얻어갈 수 있도록<br >밀도있고 효율적으로 업무를 진행하게 됩니다.</p> + <p class="promise-emph">물경력? 그런건 우리 사전에 없습니다.</p> + </div> + </div> + </div> + </section> + + <!-- ===================== 셋째 — 효율적인 업무(블루) ===================== --> + <section class="promise-third"> + <div class="wrap"> + <div class="panel-inner"> + <h3 v-reveal class="third-title"> + <span class="t-soft">셋째,</span><br >효율적인 업무를 약속해요 + </h3> + <hr class="third-divider" > + <div v-reveal="{ delay: 100 }" class="third-body"> + <p>IR? 없어도 됩니다. 투자없이 성장했거든요.</p> + <p>회의도 주 1회만 합니다.<br >보고자료 만드는데 시간쓰면 모두가 손해거든요.<br ><strong>ITAB은 개인의 역량을 믿습니다.</strong></p> + </div> + </div> + </div> + </section> + + <!-- ===================== 복지(블루 + 흰 카드) ===================== --> + <section class="welfare"> + <div class="wrap"> + <h2 v-reveal class="welfare-q">이너탭은 무슨 복지가 있나요?</h2> + + <!-- 원형 배지 3개 --> + <ul class="welfare-badges"> + <li + v-for="(b, i) in welfareBadges" + :key="b.title" + v-reveal:scale="{ delay: i * 150 }" + class="wbadge" + > + <strong>{{ b.title }}</strong> + <span>{{ b.sub }}</span> + </li> + </ul> + + <!-- 일하기 좋은 쾌적한 환경 --> + <div v-reveal class="welfare-card"> + <h3 class="welfare-card-title">#일하기 좋은 쾌적한 환경</h3> + <ul class="welfare-grid"> + <li v-for="(p, i) in envPerks" :key="p.l1" v-reveal="{ delay: i * 70 }"> + <span class="wi-emoji" aria-hidden="true"> + <svg v-if="p.desk" class="wi-desk" viewBox="0 0 64 64"> + <rect x="6" y="22" width="52" height="8" rx="2" fill="#E08B3E" /> + <rect x="11" y="30" width="5" height="24" rx="1" fill="#C2752F" /> + <rect x="48" y="30" width="5" height="24" rx="1" fill="#C2752F" /> + <rect x="36" y="30" width="17" height="16" rx="2" fill="#D67F34" /> + <rect x="40" y="37" width="9" height="2.4" rx="1.2" fill="#9C5C1C" /> + </svg> + <template v-else>{{ p.icon }}</template> + </span> + <p class="wi-title">{{ p.l1 }}</p> + <p v-if="p.l2" class="wi-sub">{{ p.l2 }}</p> + </li> + </ul> + </div> + + <!-- 아낌없는 지원 --> + <div v-reveal class="welfare-card"> + <h3 class="welfare-card-title">#아낌없는 지원</h3> + <ul class="welfare-grid welfare-grid--2"> + <li v-for="(p, i) in supportPerks" :key="p.l1" v-reveal="{ delay: i * 70 }"> + <span class="wi-emoji" aria-hidden="true">{{ p.icon }}</span> + <p class="wi-title">{{ p.l1 }}</p> + <p v-if="p.l2" class="wi-sub">{{ p.l2 }}</p> + </li> + </ul> + </div> + </div> + </section> + + <!-- ===================== 마무리 CTA ===================== --> + <section class="culture-cta"> + <div class="cta-bg" /> + <div class="cta-overlay" /> + <div class="wrap"> + <div class="cta-inner"> + <h2 v-reveal>이제 시작입니다.</h2> + <p v-reveal="{ delay: 120 }"> + 저희의 가능성을 보고 합류한 많은 인재들과 함께,<br >더욱 빠르고 가파르게 성장할 예정입니다. + </p> + <p v-reveal="{ delay: 200 }"> + 유능한 인재들과 함께 일잘러로 거듭날 수 있습니다.<br >내가 만든 제품이 주변 사람들의 일상이 될 수 있습니다. + </p> + <p v-reveal="{ delay: 280 }" class="cta-last">이 설레는 여정에 어서 합류하세요.</p> + </div> + </div> + </section> + + <AppFooter /> + </div> +</template> + +<style scoped> +/* culture 페이지의 모든 등장 애니메이션 시작 시점을 살짝 늦춤(+300ms) */ +.reveal { + transition-delay: calc(var(--reveal-delay, 0ms) + 300ms); +} + +.culture-hero { + position: relative; + /* 헤더(4.5rem)를 제외한 화면 높이를 가득 채움 */ + min-height: calc(100dvh - 4.5rem); + display: flex; + align-items: center; + justify-content: center; + overflow: hidden; + padding: clamp(2.5rem, 6vw, 5rem) var(--pad); + /* 어두운 네이비 베이스 */ + background: linear-gradient(160deg, #05122e 0%, #0a2350 56%, #0e2f63 100%); +} + +/* 카드 뒤 타원형 블루 글로우 — 좌하단→우상단 대각선으로 기울임(-45deg 회전) */ +.culture-hero::before { + content: ''; + position: absolute; + inset: -30%; /* 회전 시 모서리 빈틈 방지 위해 크게 */ + z-index: 0; + background: radial-gradient( + 34% 31% at 50% 50%, + rgba(178, 216, 255, 0.62) 0%, + rgba(95, 150, 218, 0.26) 40%, + transparent 68% + ); + transform: rotate(-45deg); + pointer-events: none; +} + +.hero-inner { + position: relative; + z-index: 1; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; +} + +/* 사원증 목걸이 — 상단 중앙 / 목걸이 끈(상단) 기준으로 좌우로 아주 살짝 흔들림 */ +.badge { + display: block; + width: auto; + height: clamp(26rem, 72vh, 44rem); /* 416~704px */ + filter: drop-shadow(0 1.75rem 3rem rgba(0, 0, 0, 0.5)); + transform-origin: top center; /* 끈 위쪽을 축으로 진자처럼 흔들림 */ + animation: badge-sway 4.5s ease-in-out infinite; +} + +@keyframes badge-sway { + 0%, + 100% { + transform: rotate(-1.5deg); + } + 50% { + transform: rotate(1.5deg); + } +} + +/* 모션 최소화 선호 시 흔들림 비활성화 */ +@media (prefers-reduced-motion: reduce) { + .badge { + animation: none; + } +} + +.brand-eyebrow { + margin-top: clamp(1.75rem, 4vw, 2.75rem); /* 28~44px */ + font-size: clamp(0.8125rem, 1.2vw, 0.9375rem); /* 13~15px */ + font-weight: 600; + letter-spacing: 0.32em; + text-indent: 0.32em; /* 자간으로 인한 좌측 쏠림 보정 */ + color: rgba(255, 255, 255, 0.72); +} + +.culture-title { + margin-top: clamp(0.5rem, 1.2vw, 0.875rem); /* 8~14px */ + font-size: clamp(2.75rem, 8vw, 5rem); /* 44~80px */ + font-weight: 800; + letter-spacing: -0.02em; + line-height: 1.05; + color: #fff; +} + +.culture-sub { + margin-top: clamp(1.25rem, 2.6vw, 2rem); /* 20~32px */ + font-size: clamp(0.9375rem, 1.6vw, 1.1875rem); /* 15~19px */ + font-weight: 400; + line-height: 1.7; + color: rgba(255, 255, 255, 0.72); +} + +/* ===================== 목표 매출 성장 그래프 ===================== */ +.growth-graph { + position: relative; + overflow: hidden; + padding: clamp(3.5rem, 9vw, 7rem) 0 clamp(4rem, 10vw, 8rem); + /* 히어로(하단 #0e2f63)에서 이어지는 다크 네이비 */ + background: linear-gradient(180deg, #0b264f 0%, #07182f 52%, #050f1e 100%); +} + +/* culture 페이지 콘텐츠 폭 — 메인(1440)보다 좁게 1000으로 */ +.growth-graph .wrap, +.promise-panel .wrap, +.promise-second .wrap, +.promise-third .wrap, +.welfare .wrap, +.culture-cta .wrap { + max-width: 62.5rem; /* 1000px */ +} + +.g-eyebrow { + font-size: clamp(1rem, 1.8vw, 1.375rem); /* 16~22px */ + font-weight: 700; + letter-spacing: -0.01em; + /* 밝은 하늘색 → 진한 블루 그라데이션 텍스트 */ + background: linear-gradient(100deg, #a6d6ff 0%, #6aa6ec 55%, #4f86d8 100%); + background-clip: text; + -webkit-background-clip: text; + color: transparent; + -webkit-text-fill-color: transparent; + width: fit-content; /* 그라데이션이 텍스트 폭에만 적용되도록 */ +} + +.g-title { + margin-top: 0.625rem; /* 10px */ + font-size: clamp(2.125rem, 5.5vw, 3.5rem); /* 34~56px */ + font-weight: 800; + letter-spacing: -0.03em; + color: #fff; + line-height: 1.2; +} + +.g-divider { + width: clamp(16rem, 38vw, 26rem); + height: 0.0625rem; /* 1px */ + border: 0; + background: rgba(255, 255, 255, 0.22); + margin: clamp(1.5rem, 3vw, 2.25rem) 0; +} + +.g-sub { + font-size: clamp(1.0625rem, 2vw, 1.4375rem); /* 17~23px */ + color: rgba(255, 255, 255, 0.62); + letter-spacing: -0.01em; +} + +.g-sub strong { + font-weight: 800; + color: #fff; +} + +/* ── 차트 ── */ +.chart { + position: relative; + width: 100%; /* 콘텐츠(wrap) 폭을 모두 차지 */ + margin: clamp(2.5rem, 6vw, 4.5rem) 0 0; +} + +.chart-svg { + display: block; + width: 100%; + height: auto; + overflow: visible; /* 끝점 글로우/라벨이 잘리지 않도록 */ +} + +/* 라인 아래 채움 영역 — reveal 클립으로 좌→우 펼쳐짐(라인 그리기와 동기화) */ +.chart-svg .area { + fill: url(#areaFill); +} + +.chart-svg .reveal-rect { + transform: scaleX(0); + transform-box: fill-box; + transform-origin: left center; + transition: transform 1.9s cubic-bezier(0.4, 0, 0.2, 1); +} + +.chart.is-animated .reveal-rect { + transform: scaleX(1); +} + +/* 메인 라인 — 좌하단→우상단으로 그려지는 등장 */ +.chart-svg .line { + fill: none; + stroke: #ffffff; + stroke-width: 2.5; + stroke-linecap: round; + stroke-linejoin: round; + /* --len: onMounted에서 측정한 실제 라인 길이(미측정 시 fallback) */ + stroke-dasharray: var(--len, 620); + stroke-dashoffset: var(--len, 620); + transition: stroke-dashoffset 1.9s cubic-bezier(0.4, 0, 0.2, 1); +} + +.chart.is-animated .line { + stroke-dashoffset: 0; +} + +/* 세로 점선 */ +.chart-svg .dropline { + fill: none; + stroke: rgba(255, 255, 255, 0.2); + stroke-width: 1; + stroke-dasharray: 3 4; + opacity: 0; + transition: opacity 0.5s ease; +} + +.chart.is-animated .dropline { + opacity: 1; +} + +/* 데이터 포인트 */ +.chart-svg .dot { + fill: #ffffff; + opacity: 0; + transform: scale(0); + transform-box: fill-box; + transform-origin: center; + transition: opacity 0.4s ease, transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1); +} + +.chart.is-animated .dot { + opacity: 1; + transform: scale(1); +} + +/* 끝점(2028) — 빛나는 강조 */ +.chart-svg .dot-glow { + fill: rgba(150, 196, 255, 0.85); +} + +.chart-svg .dot-ring { + fill: none; + stroke: rgba(255, 255, 255, 0.6); + stroke-width: 1.5; +} + +.chart-svg .dot-end { + fill: #ffffff; +} + +.chart-svg .dot-glow, +.chart-svg .dot-ring, +.chart-svg .dot-end { + opacity: 0; + transform: scale(0.4); + transform-box: fill-box; + transform-origin: center; + transition: opacity 0.6s ease 1.85s, transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) 1.85s; +} + +.chart.is-animated .dot-glow, +.chart.is-animated .dot-ring, +.chart.is-animated .dot-end { + opacity: 1; + transform: scale(1); +} + +/* 라벨 */ +.chart-svg .lbl { + opacity: 0; + transform: translateY(8px); + transition: opacity 0.5s ease, transform 0.5s ease; +} + +.chart.is-animated .lbl { + opacity: 1; + transform: translateY(0); +} + +.chart-svg .lbl-year { + fill: rgba(255, 255, 255, 0.6); + font-size: 13px; + font-weight: 500; +} + +.chart-svg .lbl-val { + fill: #ffffff; + font-size: 19px; + font-weight: 800; + letter-spacing: -0.02em; +} + +.chart-svg .lbl-val--hl { + font-size: 21px; +} + +/* 모션 최소화 선호 시 모든 차트 전환 제거 */ +@media (prefers-reduced-motion: reduce) { + .chart-svg * { + transition: none !important; + } +} + +/* ===================== 3가지 약속 인트로 ===================== */ +.promise-intro { + position: relative; + text-align: center; + padding: clamp(3.5rem, 9vw, 6.5rem) var(--pad) clamp(4.5rem, 10vw, 7rem); + /* 밝은 블루 글로우 + 네이비 (시안 색상 기반) */ + background: + radial-gradient(70% 60% at 50% 18%, rgba(15, 110, 215, 0.5) 0%, transparent 60%), + linear-gradient(180deg, #0a3877 0%, #062a5a 100%); +} + +.read-badge { + display: inline-block; + padding: 0.4375rem 1.125rem; /* 7~18px */ + border-radius: 6.25rem; + background: rgba(255, 255, 255, 0.92); + color: #0b2f63; + font-size: 0.8125rem; /* 13px */ + font-weight: 800; + letter-spacing: 0.01em; +} + +.promise-q { + margin-top: clamp(1.25rem, 2.6vw, 1.875rem); + font-size: clamp(1.75rem, 4.4vw, 2.875rem); /* 28~46px */ + font-weight: 600; + line-height: 1.34; + color: #fff; + letter-spacing: -0.02em; +} + +.promise-q strong { + font-weight: 800; +} + +.promise-chevron { + width: clamp(1.75rem, 3vw, 2.25rem); + height: clamp(1.75rem, 3vw, 2.25rem); + margin: clamp(1.5rem, 3.5vw, 2.5rem) auto 0; + color: rgba(255, 255, 255, 0.85); + animation: chevron-bob 1.8s ease-in-out infinite; +} + +@keyframes chevron-bob { + 0%, + 100% { + transform: translateY(0); + } + 50% { + transform: translateY(0.375rem); + } +} + +/* ===================== 첫째 — 보상 약속(흰 패널) ===================== */ +.promise-panel { + position: relative; + z-index: 1; + margin-top: -2rem; /* 인트로 위로 살짝 겹침 */ + background: #fff; + border-radius: 2.25rem 2.25rem 0 0; /* 상단 라운드 */ + padding: clamp(3rem, 7vw, 5.5rem) 0 clamp(4rem, 9vw, 7rem); +} + +.panel-inner { + max-width: 100%; /* 콘텐츠 폭(1000px)을 모두 사용 */ +} + +.promise-title { + font-size: clamp(1.5rem, 3.6vw, 2.375rem); /* 24~38px */ + font-weight: 800; + line-height: 1.4; + letter-spacing: -0.02em; + color: #14181f; +} + +.promise-title .t-soft { + font-weight: 600; /* 가운데 줄은 살짝 얇게 */ +} + +.panel-divider { + border: 0; + height: 0.0625rem; + background: #e7e9ee; + margin: clamp(2rem, 4.5vw, 3.25rem) 0; +} + +.panel-eyebrow { + text-align: center; + font-size: clamp(0.875rem, 1.4vw, 1rem); /* 14~16px */ + font-weight: 800; + letter-spacing: 0.02em; + color: #3b73d6; +} + +.panel-head { + text-align: center; + margin-top: clamp(0.75rem, 1.6vw, 1.125rem); + font-size: clamp(1.375rem, 3vw, 2rem); /* 22~32px */ + font-weight: 800; + letter-spacing: -0.02em; + color: #14181f; +} + +.panel-sub { + text-align: center; + margin-top: clamp(1rem, 2vw, 1.5rem); + font-size: clamp(0.9375rem, 1.5vw, 1.125rem); /* 15~18px */ + line-height: 1.7; + color: #6a7180; +} + +.panel-sub strong { + font-weight: 800; + color: #14181f; +} + +/* ── RULE 카드 ── */ +.rule-list { + list-style: none; + margin: clamp(2.25rem, 5vw, 3.5rem) 0 0; + display: flex; + flex-direction: column; + gap: clamp(0.875rem, 1.8vw, 1.25rem); +} + +.rule-card { + display: flex; + align-items: center; + gap: clamp(1rem, 3vw, 2.25rem); + background: #f4f8fe; + border: 0.09375rem dashed #b3d0f2; /* 1.5px */ + border-radius: 1rem; /* 16px */ + padding: clamp(1.125rem, 2.6vw, 1.625rem) clamp(1.25rem, 3.2vw, 2.125rem); +} + +.rule-no { + flex: none; + width: clamp(3.5rem, 7vw, 4.75rem); + color: #2f6fd0; + font-weight: 800; + font-size: clamp(0.9375rem, 1.5vw, 1.0625rem); /* 15~17px */ + letter-spacing: -0.01em; +} + +.rule-text { + font-size: clamp(0.875rem, 1.4vw, 1rem); /* 14~16px */ + line-height: 1.6; + color: #515967; +} + +.rule-text mark { + background: none; + color: #e23b3b; /* 빨강 강조 */ + font-weight: 700; +} + +/* 좁은 화면 — RULE 라벨을 텍스트 위로 */ +@media (max-width: 32.5rem) { + .rule-card { + flex-direction: column; + align-items: flex-start; + gap: 0.5rem; + } +} + +/* ── 둘째 — 커리어 성장(회색 섹션) ── */ +.promise-second { + background: #f3f4f6; /* 연한 회색 */ + padding: clamp(3rem, 7vw, 5.5rem) 0 clamp(4rem, 9vw, 7rem); +} + +.promise-body p { + font-size: clamp(0.9375rem, 1.5vw, 1.0625rem); /* 15~17px */ + line-height: 1.7; + color: #6a7180; +} + +.promise-body p + p { + margin-top: clamp(1.25rem, 2.5vw, 1.75rem); +} + +.promise-body strong { + font-weight: 800; + color: #14181f; +} + +.promise-body .promise-emph { + margin-top: clamp(1.75rem, 3.5vw, 2.5rem); + color: #e23b3b; /* 빨강 강조 */ + font-weight: 800; +} + +/* ===================== 셋째 — 효율적인 업무(블루) ===================== */ +.promise-third { + background: #fff; /* 흰색 (푸른 그라데이션은 복지 섹션 전용) */ + padding: clamp(3.5rem, 9vw, 6.5rem) 0 clamp(4.5rem, 11vw, 8rem); +} + +.third-title { + font-size: clamp(1.5rem, 3.6vw, 2.375rem); /* 24~38px */ + font-weight: 800; + line-height: 1.4; + letter-spacing: -0.02em; + color: #14181f; +} + +.third-title .t-soft { + font-weight: 600; +} + +/* 셋째 제목 아래 경계선 */ +.third-divider { + border: 0; + height: 0.0625rem; + background: #e7e9ee; + margin: clamp(1.75rem, 4vw, 2.75rem) 0 0; +} + +.third-body { + margin-top: clamp(2rem, 5vw, 3.5rem); +} + +.third-body p { + font-size: clamp(0.9375rem, 1.5vw, 1.0625rem); /* 15~17px */ + line-height: 1.7; + color: #6a7180; +} + +.third-body p + p { + margin-top: clamp(1.25rem, 2.5vw, 1.75rem); +} + +.third-body strong { + font-weight: 800; + color: #14181f; +} + +/* ===================== 복지(블루 배경 + 흰 카드) ===================== */ +.welfare { + /* 셋째 블루에서 이어지는 블루 — 위에서 아래로 약간 진해짐 */ + background: linear-gradient(180deg, #2a6fc4 0%, #1a5298 100%); + padding: clamp(3.5rem, 9vw, 6rem) 0 clamp(4.5rem, 11vw, 8rem); +} + +.welfare-q { + font-size: clamp(1.5rem, 3.6vw, 2.375rem); /* 24~38px */ + font-weight: 800; + letter-spacing: -0.02em; + color: #fff; +} + +/* 원형 배지 3개 */ +.welfare-badges { + list-style: none; + display: flex; + justify-content: center; + gap: clamp(0.875rem, 2.5vw, 2rem); + /* 원형 배지 위아래 여백 — 넉넉하게 */ + margin: clamp(3.25rem, 6.5vw, 5rem) 0 clamp(3.25rem, 6.5vw, 5rem); +} + +.wbadge { + flex: 1 1 0; + max-width: 12.5rem; /* 200px */ + aspect-ratio: 1; + border-radius: 50%; + background: rgba(255, 255, 255, 0.12); + border: 0.0625rem solid rgba(255, 255, 255, 0.28); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 0.375rem; + text-align: center; + padding: 0.5rem; + color: #fff; +} + +.wbadge strong { + font-weight: 800; + font-size: clamp(0.9375rem, 1.6vw, 1.1875rem); /* 15~19px */ + letter-spacing: -0.01em; +} + +/* 배지 등장 — 작게 시작해 오버슈트하며 통통 튀는 팝(뽁뽁뽁) */ +.wbadge.reveal { + opacity: 0; + transition: + opacity 0.3s ease, + transform 0.55s cubic-bezier(0.34, 1.7, 0.45, 1); /* 오버슈트 */ + transition-delay: calc(var(--reveal-delay, 0ms) + 300ms); +} + +.wbadge.reveal-scale { + transform: scale(0.2); +} + +.wbadge.reveal.is-revealed { + opacity: 1; + transform: scale(1); +} + +@media (prefers-reduced-motion: reduce) { + .wbadge.reveal { + transition: none; + opacity: 1; + transform: none; + } +} + +.wbadge span { + font-size: clamp(0.75rem, 1.3vw, 0.9375rem); /* 12~15px */ + color: rgba(255, 255, 255, 0.82); +} + +/* 흰 카드 */ +.welfare-card { + background: #fff; + border-radius: 1.5rem; /* 24px */ + padding: clamp(1.75rem, 4vw, 3rem) clamp(1.5rem, 3.5vw, 2.5rem); + margin-top: clamp(1.5rem, 3.5vw, 2.5rem); + box-shadow: 0 1.5rem 3rem -1.5rem rgba(0, 20, 50, 0.35); +} + +.welfare-card-title { + color: #3b73d6; + font-weight: 800; + font-size: clamp(1.0625rem, 1.8vw, 1.375rem); /* 17~22px */ + letter-spacing: -0.01em; + margin-bottom: clamp(1.5rem, 3.2vw, 2.5rem); +} + +.welfare-grid { + list-style: none; + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: clamp(1.75rem, 3.5vw, 2.75rem) clamp(1rem, 2vw, 1.5rem); +} + +.welfare-grid--2 { + grid-template-columns: repeat(2, 1fr); +} + +.welfare-grid li { + display: flex; + flex-direction: column; + align-items: center; + text-align: center; +} + +.wi-emoji { + font-size: clamp(2.875rem, 5.5vw, 3.75rem); /* 46~60px — 전체적으로 키움 */ + line-height: 1; + margin-bottom: 1rem; /* 이모지↔제목 — 살짝 벌림 */ +} + +/* 책상 SVG — 이모지와 동일 크기로 */ +.wi-desk { + width: 1em; + height: 1em; + display: block; +} + +.wi-title { + font-size: clamp(0.8125rem, 1.3vw, 0.9375rem); /* 13~15px */ + font-weight: 700; + color: #1b1f27; + line-height: 1.45; +} + +.wi-sub { + margin-top: 0.1875rem; /* 제목↔보조 — 좁힘(3px) */ + font-size: clamp(0.75rem, 1.2vw, 0.875rem); /* 12~14px */ + color: #8a909c; + line-height: 1.45; +} + +/* 좁은 화면 — 배지/그리드 열 축소 */ +@media (max-width: 32.5rem) { + .welfare-grid { + grid-template-columns: repeat(2, 1fr); + } +} + +/* ===================== 마무리 CTA ===================== */ +.culture-cta { + position: relative; + overflow: hidden; + padding: clamp(5rem, 12vw, 9rem) 0; +} + +.culture-cta .cta-bg { + position: absolute; + inset: 0; + z-index: 0; + background: url('/images/img-banner.png') center / cover no-repeat; +} + +.culture-cta .cta-overlay { + position: absolute; + inset: 0; + z-index: 1; + /* 다크 네이비 오버레이 — 좌측을 더 진하게(텍스트 가독성) */ + background: linear-gradient( + 90deg, + rgba(7, 18, 42, 0.94) 0%, + rgba(7, 18, 42, 0.82) 52%, + rgba(7, 18, 42, 0.55) 100% + ); +} + +.culture-cta .wrap { + position: relative; + z-index: 2; +} + +.cta-inner { + max-width: 45rem; /* 720px */ + color: #fff; +} + +.cta-inner h2 { + font-size: clamp(1.875rem, 4.4vw, 3rem); /* 30~48px */ + font-weight: 800; + letter-spacing: -0.02em; + line-height: 1.2; +} + +.cta-inner p { + margin-top: clamp(1.25rem, 2.6vw, 1.875rem); + font-size: clamp(0.9375rem, 1.5vw, 1.125rem); /* 15~18px */ + line-height: 1.75; + color: rgba(255, 255, 255, 0.8); +} + +.cta-inner .cta-last { + margin-top: clamp(1.75rem, 3.5vw, 2.5rem); + font-weight: 700; + color: #fff; +} +</style> diff --git a/frontend/pages/index.vue b/frontend/pages/index.vue index 400e85d..43ae012 100644 --- a/frontend/pages/index.vue +++ b/frontend/pages/index.vue @@ -1,5 +1,11 @@ <script setup lang="ts"> // 메인(채용 홈) — Hero / About / 브랜드 / Growth / People / CTA + +// 연혁 행 우측에 붙일 이미지 — assets 이미지는 import해야 Vite가 URL로 변환 +import imgUsa from '~/assets/images/img-usa.svg' +import imgHongkong from '~/assets/images/img-hongkong.svg' +import imgBrand from '~/assets/images/img-brand.svg' + const config = useRuntimeConfig() const siteUrl = String(config.public.siteUrl || '').replace(/\/$/, '') @@ -8,6 +14,8 @@ useSeo({ description: '이너탭(innertab)은 2023년 창립 이후 꾸준히 성장하는 D2C 스타트업입니다. 셀라이트·리큐어리 등 다양한 브랜드로 고객에게 꼭 필요한 해답을 제공합니다. 함께 성장할 동료를 찾습니다.', path: '/', + keywords: + '이너탭, innertab, D2C, 스타트업, 채용, 브랜드, 셀라이트, 리큐어리, 조직문화, 커리어, 함께 성장, 채용 중', }) // 조직 구조화 데이터(JSON-LD) — 검색엔진의 회사 정보 인식 @@ -34,9 +42,35 @@ useHead({ sameAs: ['https://selite.kr', 'https://retriq.co.kr'], }), }, + { + // 웹사이트 정보 — 검색결과의 사이트명 인식 + type: 'application/ld+json', + innerHTML: JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'WebSite', + name: '이너탭 innertab', + alternateName: '이너탭 채용', + url: siteUrl, + inLanguage: 'ko-KR', + publisher: { '@type': 'Organization', name: '이너탭', url: siteUrl }, + }), + }, ], }) +// Growth 배경 영상 — 슬로우 모션 적용 (재생 속도 0.5배) +const growthVideo = ref<HTMLVideoElement | null>(null) +const GROWTH_PLAYBACK_RATE = 0.5 // 슬로우 배율 (1 = 원본 속도) +onMounted(() => { + if (!growthVideo.value) return + // playbackRate는 새 소스가 로드될 때 초기화되므로 메타데이터 로드 시점에도 재설정 + const applyRate = () => { + if (growthVideo.value) growthVideo.value.playbackRate = GROWTH_PLAYBACK_RATE + } + applyRate() + growthVideo.value.addEventListener('loadedmetadata', applyRate) +}) + // 브랜드 타일 데이터 interface BrandTile { name: string @@ -44,11 +78,12 @@ interface BrandTile { feature?: boolean link?: string // 외부 링크 URL (없으면 출시예정) comingSoon?: boolean // 출시예정 여부 + cuteFont?: boolean // 동글동글한 귀여운 폰트(Jua) 적용 여부 } const brands: BrandTile[] = [ - { name: 'selite', img: '/images/img-selite.png', link: 'https://selite.kr' }, - { name: 'recurely', img: '/images/img-recurely.png', link: 'https://retriq.co.kr' }, - { name: 'nyangtea', img: '/images/img-nyangtea.png', comingSoon: true }, + { name: "s'elite", img: '/images/img-selite.png', link: 'https://selite.kr' }, + { name: 'RETRIQ', img: '/images/img-recurely.png', link: 'https://retriq.co.kr' }, + { name: '냥티', img: '/images/img-nyangtea.png', comingSoon: true, cuteFont: true }, ] // 성장 지표 데이터 @@ -58,23 +93,42 @@ interface Stat { unit: string desc: string } +// 연 매출 성장률 — 상단 단독 카드: 좌→우로 커지고 진해지는 겹친 구체 3개 다이어그램 +const revenueTitle = '연 매출 성장률' +const revenueDesc = '고객의 믿음과 선택으로 이너탭은 꾸준히 성장해왔습니다.' +interface RevenueOrb { + year: string + value?: number // 숫자 매출 (CountUp 카운트 애니메이션) + unit?: string + text?: string // 숫자 대신 표시할 텍스트 (예: 창립) + plus?: boolean // 마지막 구체에 + 배지 표시 +} +const revenueOrbs: RevenueOrb[] = [ + { year: '2023년', text: '창립' }, + { year: '2024년', value: 55, unit: '억' }, + { year: '2026년', value: 150, unit: '억', plus: true }, +] + +// 나머지 지표 — 매출 성장률 카드 아래에 3개 나란히 배치 const stats: Stat[] = [ { title: '운영 브랜드', value: 5, unit: '개', desc: '서로 다른 문제를 해결하기 위해\n각기 다른 브랜드를 정교하게 설계했습니다.' }, - { title: '누적 매출', value: 150, unit: '억', desc: '고객의 믿음과 선택으로\n이너탭은 꾸준히 성장해왔습니다.' }, { title: '연 평균 성장률', value: 320, unit: '%', desc: '끊임없는 도전과 실행으로\n이너탭은 더 빠르게 확장하고 있습니다.' }, { title: '더 나은 일상을 연구한 시간', value: 1200, unit: '일', desc: '작은 변화가 만드는 큰 차이를\n매일 관찰하고 개선해왔습니다.' }, ] -// 주요 연혁 — 년도 + 내용 +// 주요 연혁 — 년도 + 내용 (+ 행 우측 이미지) interface HistoryItem { year: string text: string + img?: string // 행 오른쪽 끝에 표시할 이미지 (없으면 미표시) + label?: string // 이미지 대신 표시할 텍스트 배지 (예: ITAB) } const history: HistoryItem[] = [ - { year: '2026', text: '일 최대 매출 4,500만원 달성' }, - { year: '2026', text: '미국 법인 설립' }, - { year: '2025', text: '홍콩 법인 설립' }, - { year: '2025', text: '한국 소비자 평가 대상 2회' }, + { year: '2026', text: '일 최대 매출 4,500만원 달성', label: 'ITAB' }, + { year: '2026', text: '미국 법인 설립', img: imgUsa }, + { year: '2025', text: '운영 브랜드 4개 달성' }, + { year: '2025', text: '홍콩 K-Beauty 진출', img: imgHongkong }, + { year: '2025', text: '한국 소비자 평가 대상 2연속 수상', img: imgBrand }, ] // 구성원 카드 — PEOPLE 섹션 비활성화로 함께 주석 처리 (재활성화 시 아래 + 템플릿 주석 해제) @@ -105,15 +159,14 @@ const history: HistoryItem[] = [ source 우선순위: WebM(VP9, 더 작음) → MP4(폴백) --> <video class="hero-video" - poster="/images/hero-poster.webp" + poster="/images/hero2-poster.jpg" autoplay muted loop playsinline preload="auto" > - <source src="/videos/hero.webm" type="video/webm" > - <source src="/videos/hero-opt.mp4" type="video/mp4" > + <source src="/videos/hero2.mp4" type="video/mp4" > </video> <div class="scroll-hint"><span>SCROLL</span><i /></div> </section> @@ -122,10 +175,10 @@ const history: HistoryItem[] = [ <section id="mission" class="about"> <div class="wrap"> <div class="inner"> - <p v-reveal class="about-eyebrow">누군가의 매일을 더 낫게 만드는 일</p> - <h2 v-reveal="{ delay: 100 }" class="m-title">고객만을 위한 <mark>해답</mark>을 제공합니다.</h2> + <p v-reveal="{ delay: 220 }" class="about-eyebrow">누군가의 매일을 더 낫게 만드는 일</p> + <h2 v-reveal="{ delay: 340 }" class="m-title">고객만을 위한 <mark>해답</mark>을 제공합니다.</h2> - <p v-reveal="{ delay: 160 }" class="about-intro"> + <p v-reveal="{ delay: 420 }" class="about-intro"> 이너탭은 2023년 창립 이후 꾸준히 성장하고 있는 D2C 스타트업입니다.<br > 올리브 캡슐 ‘올베라진’, 밀크씨슬 브랜드 ‘리필앤칸 액티브’ 등<br > 다양한 비즈니스로 고객에게 다가가고 있습니다. @@ -133,14 +186,14 @@ const history: HistoryItem[] = [ <!-- 미션 / 비전 — 라벨 + 영문 타이틀 + 국문 설명 (구분선 분리) --> <dl class="mv-list"> - <div v-reveal class="mv-row"> + <div v-reveal="{ delay: 520 }" class="mv-row"> <dt class="mv-label">Mission</dt> <dd class="mv-content"> <h3 class="mv-title">Build Better. Sell Bester</h3> <p class="mv-desc">고객에게 필요한 제품을 잘 만들고,<br >그 가치를 누구보다 잘 전달합니다.</p> </dd> </div> - <div v-reveal="{ delay: 100 }" class="mv-row"> + <div v-reveal="{ delay: 640 }" class="mv-row"> <dt class="mv-label">Vision</dt> <dd class="mv-content"> <h3 class="mv-title">Be the Brand Found on the Desks of People We Love</h3> @@ -166,7 +219,7 @@ const history: HistoryItem[] = [ > <img :src="brand.img" :alt="`${brand.name} 브랜드 이미지`" > <div class="tile-overlay" /> - <span class="tile-name">{{ brand.name }}</span> + <span class="tile-name" :class="{ 'tile-name--cute': brand.cuteFont }">{{ brand.name }}</span> <!-- 출시예정 배지 / 외부링크 화살표 --> <span v-if="brand.comingSoon" class="tile-badge">출시예정</span> <span v-else class="tile-arrow" aria-hidden="true">↗</span> @@ -180,6 +233,7 @@ const history: HistoryItem[] = [ <!-- 배경 영상 — 히어로와 동일하게 무한 반복 / poster·WebM·MP4 폴백 --> <div class="growth-bg"> <video + ref="growthVideo" class="growth-video" poster="/images/growth-poster.webp" autoplay @@ -201,6 +255,55 @@ const history: HistoryItem[] = [ </div> <div class="growth-layout"> + <!-- 상단 행: 연 매출 성장률(콘텐츠 폭) + 주요 연혁(남는 폭 채움) --> + <div class="growth-top"> + <!-- 연 매출 성장률 — 콘텐츠(구체 클러스터) 크기만큼만 폭 차지 --> + <div v-reveal class="gcard stat-card revenue-card"> + <div class="gcard-title">{{ revenueTitle }}</div> + <!-- 겹친 구체 클러스터: 왼쪽이 작고 옅으며, 오른쪽으로 갈수록 커지고 진해짐 --> + <div class="orb-cluster"> + <div + v-for="(orb, i) in revenueOrbs" + :key="orb.year" + class="stat-orb" + :class="`orb-${i + 1}`" + > + <span class="orb-label"> + <span class="orb-year">{{ orb.year }}</span> + <span class="orb-value"> + <!-- 숫자 매출이면 CountUp + 단위, 아니면 텍스트(창립 등) --> + <template v-if="orb.value !== undefined"> + <CountUp :value="orb.value" /><small>{{ orb.unit }}</small><span v-if="orb.plus" class="plus">+</span> + </template> + <template v-else>{{ orb.text }}</template> + </span> + </span> + </div> + </div> + <!-- 카드 하단 설명 --> + <p class="revenue-desc">{{ revenueDesc }}</p> + </div> + + <!-- 주요 연혁 — 매출 카드 옆 남는 공간을 채움 --> + <div v-reveal="{ delay: 120 }" class="gcard history-card"> + <div class="gcard-title">주요 연혁 내역</div> + <!-- 슬로건 — 연혁 카드에 메시지 부여 --> + <p class="history-slogan">끊임없는 도전으로 써내려간 성장의 기록</p> + <ul class="timeline"> + <li v-for="(item, i) in history" :key="i" v-reveal="{ delay: 200 + i * 90 }"> + <!-- 같은 년도가 연속되면 시각적으로 묶어 표기 --> + <span class="t-year">{{ item.year }}</span> + <span class="t-text">{{ item.text }}</span> + <!-- 행 오른쪽 끝 이미지 (해당 항목에만) --> + <img v-if="item.img" :src="item.img" class="t-flag" :alt="`${item.text} 이미지`" > + <!-- 이미지가 없는 행은 텍스트 배지(ITAB 등)로 동일 높이 유지 --> + <span v-else-if="item.label" class="t-label">{{ item.label }}</span> + </li> + </ul> + </div> + </div> + + <!-- 하단 행: 나머지 지표 3개 나란히 (전체 폭) --> <div class="stat-grid"> <div v-for="(stat, i) in stats" @@ -220,21 +323,6 @@ const history: HistoryItem[] = [ </p> </div> </div> - - <div v-reveal="{ delay: 120 }" class="gcard history-card"> - <div class="gcard-title">주요 연혁 내역</div> - <!-- 슬로건 — 연혁 카드에 메시지 부여 --> - <p class="history-slogan">끊임없는 도전으로 써내려간 성장의 기록</p> - <ul class="timeline"> - <li v-for="(item, i) in history" :key="i" v-reveal="{ delay: 200 + i * 90 }"> - <!-- 같은 년도가 연속되면 시각적으로 묶어 표기 --> - <span class="t-year" :class="{ 'is-repeat': i > 0 && history[i - 1].year === item.year }"> - {{ item.year }} - </span> - <span class="t-text">{{ item.text }}</span> - </li> - </ul> - </div> </div> </div> </section> @@ -295,6 +383,8 @@ const history: HistoryItem[] = [ .hero { position: relative; overflow: hidden; + /* 헤더(4.5rem)를 제외한 화면 높이를 가득 채움 — dvh로 모바일 주소창 변동 대응 */ + height: calc(100dvh - 4.5rem); /* 영상 로드 전 폴백 배경 — 흰 섹션으로 즉시 표시 */ background: var(--white); } @@ -302,10 +392,8 @@ const history: HistoryItem[] = [ .hero-video { display: block; width: 100%; /* 가로폭을 꽉 채움 */ - height: auto; /* 높이는 원본 비율대로 — 가로폭만큼 커짐 */ - aspect-ratio: 16 / 9; /* 원본 1280x720 비율 — 로드 전 높이 예약 */ - max-height: 62.5rem; /* 최대 높이 제한 */ - object-fit: cover; /* 높이 제한에 걸리면 늘어나지 않고 크롭 (poster에도 동일 적용) */ + height: 100%; /* 섹션 높이(화면-헤더)를 가득 채움 */ + object-fit: cover; /* 비율 유지하며 영역을 채우고 넘치는 부분은 크롭 (poster에도 동일 적용) */ /* 로드 시 살짝 확대된 상태에서 천천히 안착 (Ken Burns) */ animation: hero-settle 2.6s cubic-bezier(0.16, 1, 0.3, 1) both; } @@ -535,7 +623,7 @@ const history: HistoryItem[] = [ font-weight: 800; letter-spacing: 0.01em; line-height: 1; - text-transform: uppercase; + /* 표기는 데이터의 원본 대소문자 그대로 — s'elite 소문자 유지 */ font-size: clamp(1.125rem, 1.6vw, 1.5rem); /* 18~24px */ pointer-events: none; text-shadow: 0 0.125rem 1rem rgba(0, 0, 0, 0.35); @@ -545,6 +633,15 @@ const history: HistoryItem[] = [ font-size: clamp(1.75rem, 2.8vw, 2.625rem); /* 28~42px */ } +/* 냥티 등 동글동글하고 귀여운 폰트(Jua) 적용 타일명 + — .btile .tile-name(클래스 2개)보다 우선순위가 높아야 하므로 동일하게 .btile 하위로 작성 */ +.btile .tile-name--cute { + font-family: 'Jua', var(--font-display), sans-serif; + font-weight: 400; /* Jua는 단일 weight — 800 강제 시 가짜 볼드로 둥근 형태가 뭉개짐 */ + letter-spacing: 0.02em; + font-size: clamp(1.375rem, 2vw, 1.875rem); /* 22~30px — 둥근 폰트 가독성 확보 위해 약간 확대 */ +} + .btile .tile-arrow { position: absolute; right: clamp(1rem, 1.6vw, 1.375rem); /* 16~22px */ @@ -640,19 +737,138 @@ const history: HistoryItem[] = [ color: var(--ink); } +/* 세로 스택 — 상단 행(매출+연혁) → 하단 행(지표 3개) */ .growth-layout { - display: grid; - grid-template-columns: 1.45fr 1fr; + display: flex; + flex-direction: column; gap: clamp(1rem, 1.8vw, 1.5rem); /* 16~24px */ - align-items: stretch; +} + +/* 상단 행 — 매출 카드(콘텐츠 폭) + 연혁 카드(남는 폭 채움) */ +.growth-top { + display: flex; + gap: clamp(1rem, 1.8vw, 1.5rem); + align-items: stretch; /* 두 카드 높이 맞춤 */ } .stat-grid { display: grid; - grid-template-columns: 1fr 1fr; + grid-template-columns: repeat(3, 1fr); /* 지표 3개 나란히 — 전체 폭이라 카드 폭 충분 */ gap: clamp(1rem, 1.8vw, 1.5rem); } +/* ===== 연 매출 성장률 — 콘텐츠(구체 클러스터) 크기만큼만 폭 차지 ===== */ +.revenue-card { + /* 제목(좌상단) + 구체 클러스터(아래) 세로 배치 */ + display: flex; + flex-direction: column; + flex: 0 0 auto; /* 늘어/줄지 않고 콘텐츠 폭 유지 */ + max-width: 100%; /* 좁은 화면에서 넘침 방지 */ +} + +/* 겹친 구체 클러스터 — 제목 아래 남는 공간을 채우고 그 안에서 세로 중앙 배치 */ +.revenue-card .orb-cluster { + position: relative; + z-index: 0; + display: flex; + flex: 1; /* 카드가 늘어나도 남는 높이를 채움 → 구체가 윗단에 몰리지 않음 */ + align-items: center; /* 늘어난 영역 안에서 구체를 세로 중앙 정렬 */ + margin-top: clamp(0.75rem, 1.5vw, 1.25rem); + pointer-events: none; +} + +/* 클러스터 내부 구체 — 단독 카드용 위치 규칙 무시(static)하고 흐름 배치 */ +.revenue-card .orb-cluster .stat-orb { + position: static; + display: grid; + place-items: center; /* 내부 텍스트 중앙 정렬 */ + flex: none; + aspect-ratio: 1; + border-radius: 50%; + /* 기존 단일 구체와 동일한 방사형 그라데이션 */ + background: radial-gradient( + circle at 50% 42%, + rgba(255, 255, 255, 0.95), + rgba(255, 255, 255, 0.55) 54%, + rgba(255, 255, 255, 0) 78% + ); +} + +/* 좌→우로 커지는 구체 크기 */ +.revenue-card .orb-1 { + width: clamp(6rem, 11vw, 9rem); + opacity: 0.5; /* 가장 옅게 */ +} + +.revenue-card .orb-2 { + width: clamp(7.5rem, 14vw, 11.5rem); + opacity: 0.74; + margin-left: clamp(-2.75rem, -4.5vw, -3.75rem); /* 앞 구체와 겹침 */ +} + +/* 마지막 구체 — 가장 크고 기존 단일 구체와 동일한 불투명도(opacity 미지정 = 1) + DOM 순서상 뒤에 있어 위에 그려지며 가장 진하게 앞으로 옴 */ +.revenue-card .orb-3 { + width: clamp(9.5rem, 17vw, 14rem); + margin-left: clamp(-3.25rem, -5.5vw, -4.5rem); +} + +/* 구체 내부 텍스트 라벨 — 연도(상단) + 큰 숫자 */ +.revenue-card .orb-label { + position: relative; + z-index: 1; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + color: var(--ink); + line-height: 1.1; +} + +.revenue-card .orb-year { + font-weight: 700; + font-size: clamp(0.8125rem, 1.3vw, 1.0625rem); /* 13~17px */ + letter-spacing: -0.01em; + margin-bottom: 0.25em; +} + +.revenue-card .orb-value { + font-weight: 800; + letter-spacing: -0.03em; + white-space: nowrap; +} + +/* 숫자 크기도 구체 크기에 맞춰 좌→우로 확대 */ +.revenue-card .orb-1 .orb-value { + font-size: clamp(1.375rem, 2.6vw, 2.125rem); /* 22~34px */ +} + +.revenue-card .orb-2 .orb-value { + font-size: clamp(1.75rem, 3.4vw, 2.75rem); /* 28~44px */ +} + +.revenue-card .orb-3 .orb-value { + font-size: clamp(2.25rem, 4.6vw, 3.5rem); /* 36~56px */ +} + +/* 단위(억) — 숫자보다 작게 */ +.revenue-card .orb-value small { + font-size: 0.36em; + font-weight: 700; + margin-left: 0.15rem; + letter-spacing: 0; +} + +/* 카드 하단 설명 — 구체 클러스터 아래 */ +.revenue-card .revenue-desc { + position: relative; + z-index: 1; + margin-top: clamp(1rem, 2vw, 1.5rem); + font-size: 0.875rem; /* 14px */ + color: var(--ink-soft); + line-height: 1.65; +} + .gcard { position: relative; background: rgba(255, 255, 255, 0.18); @@ -742,6 +958,8 @@ const history: HistoryItem[] = [ .history-card { display: flex; flex-direction: column; + flex: 1 1 0; /* 매출 카드 옆 남는 폭을 모두 채움 */ + min-width: 0; } /* 연혁 슬로건 — 제목 아래 메시지 */ @@ -758,13 +976,16 @@ const history: HistoryItem[] = [ margin-top: clamp(1.25rem, 2.5vw, 1.875rem); /* 20~30px */ display: flex; flex-direction: column; + flex: 1; /* 카드 높이가 늘어날 때 항목 간격을 채워 균형 유지 */ + justify-content: center; } .timeline li { display: flex; gap: 1rem; /* 16px */ - align-items: baseline; - padding: clamp(0.9375rem, 1.6vw, 1.1875rem) 0; /* 15~19px */ + align-items: center; /* 텍스트와 이미지를 세로 중앙 정렬 */ + padding: 0; /* 행 상하 여백 제거 */ + min-height: clamp(2.625rem, 3.9vw, 3.375rem); /* 이미지 높이와 동일 — 이미지 없는 행도 균일 */ border-top: 0.0625rem solid rgba(40, 50, 70, 0.1); } @@ -784,11 +1005,6 @@ const history: HistoryItem[] = [ line-height: 1.4; } -/* 직전 항목과 같은 년도면 흐리게 → 같은 해 묶음으로 인식 */ -.timeline .t-year.is-repeat { - opacity: 0.28; -} - .timeline .t-text { font-size: 0.9375rem; /* 15px */ color: var(--ink); @@ -796,6 +1012,32 @@ const history: HistoryItem[] = [ line-height: 1.4; } +/* 행 오른쪽 끝 이미지 — 비율이 달라도 동일한 정사각 박스로 통일 */ +.timeline .t-flag { + flex: none; + margin-left: auto; /* 우측 끝단으로 밀착 */ + align-self: center; + width: clamp(2.625rem, 3.9vw, 3.375rem); /* 42~54px — 가로/세로 동일 (직전 대비 75%) */ + height: clamp(2.625rem, 3.9vw, 3.375rem); + border-radius: 0.25rem; /* 4px — 사각 이미지 모서리 살짝 둥글게 */ + object-fit: contain; /* 박스 안에서 비율 유지하며 맞춤(왜곡 없음) */ +} + +/* 이미지 대신 들어가는 텍스트 배지(ITAB) — 이미지와 동일한 높이로 행 높이 통일 */ +.timeline .t-label { + flex: none; + margin-left: auto; /* 우측 끝단으로 밀착 */ + display: grid; + place-items: center; + height: clamp(2.625rem, 3.9vw, 3.375rem); /* t-flag와 동일 높이 */ + font-family: var(--font-display); + font-weight: 700; + font-size: clamp(1.25rem, 2vw, 1.625rem); /* 20~26px */ + letter-spacing: 0.04em; + color: var(--brand); /* 브랜드 컬러 */ + line-height: 1; +} + /* ===================== PEOPLE ===================== */ .people { padding: clamp(4.5rem, 11vw, 9.375rem) 0; /* 72~150px */ @@ -933,8 +1175,9 @@ const history: HistoryItem[] = [ /* ===================== 반응형 ===================== */ @media (max-width: 56.25rem) { /* 900px */ - .growth-layout { - grid-template-columns: 1fr; + /* 상단 행: 좁은 화면에서는 매출/연혁 카드를 세로로 쌓고 전체 폭 사용 */ + .growth-top { + flex-direction: column; } .brand-bento { diff --git a/frontend/public/images/hero2-poster.jpg b/frontend/public/images/hero2-poster.jpg new file mode 100644 index 0000000..f55ed8a Binary files /dev/null and b/frontend/public/images/hero2-poster.jpg differ diff --git a/frontend/public/og-logo.jpg b/frontend/public/og-logo.jpg new file mode 100644 index 0000000..01a6d33 Binary files /dev/null and b/frontend/public/og-logo.jpg differ diff --git a/frontend/public/sitemap.xml b/frontend/public/sitemap.xml index d8abcaa..f66cb6f 100644 --- a/frontend/public/sitemap.xml +++ b/frontend/public/sitemap.xml @@ -6,6 +6,12 @@ <changefreq>weekly</changefreq> <priority>1.0</priority> </url> + <url> + <loc>https://innertab.co.kr/culture</loc> + <lastmod>2026-06-03</lastmod> + <changefreq>monthly</changefreq> + <priority>0.9</priority> + </url> <url> <loc>https://innertab.co.kr/coffee-chat</loc> <lastmod>2026-06-01</lastmod> diff --git a/frontend/public/videos/hero2.mp4 b/frontend/public/videos/hero2.mp4 new file mode 100644 index 0000000..29d7d79 Binary files /dev/null and b/frontend/public/videos/hero2.mp4 differ