Files
inneratb/frontend/pages/index.vue
T
2026-06-03 23:24:28 +09:00

1422 lines
43 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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(/\/$/, '')
useSeo({
title: '이너탭(innertab) — 누군가의 매일을 더 낫게 만드는 일',
description:
'이너탭(innertab)은 2023년 창립 이후 꾸준히 성장하는 D2C 스타트업입니다. 셀라이트·리큐어리 등 다양한 브랜드로 고객에게 꼭 필요한 해답을 제공합니다. 함께 성장할 동료를 찾습니다.',
path: '/',
keywords:
'이너탭, innertab, D2C, 스타트업, 채용, 브랜드, 셀라이트, 리큐어리, 조직문화, 커리어, 함께 성장, 채용 중',
})
// 조직 구조화 데이터(JSON-LD) — 검색엔진의 회사 정보 인식
useHead({
script: [
{
type: 'application/ld+json',
innerHTML: JSON.stringify({
'@context': 'https://schema.org',
'@type': 'Organization',
name: '이너탭',
alternateName: 'innertab',
url: siteUrl,
logo: `${siteUrl}/images/img-itab.png`,
email: 'innertab@gmail.com',
foundingDate: '2023',
address: {
'@type': 'PostalAddress',
addressCountry: 'KR',
addressRegion: '서울특별시',
addressLocality: '강남구',
streetAddress: '삼성동 121-38, 304호',
},
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
img: string
feature?: boolean
link?: string // 외부 링크 URL (없으면 출시예정)
comingSoon?: boolean // 출시예정 여부
cuteFont?: boolean // 동글동글한 귀여운 폰트(Jua) 적용 여부
}
const brands: BrandTile[] = [
{ 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 },
]
// 성장 지표 데이터
interface Stat {
title: string
value: number
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: 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만원 달성', label: 'ITAB' },
{ year: '2026', text: '미국 법인 설립', img: imgUsa },
{ year: '2025', text: '운영 브랜드 4개 달성' },
{ year: '2025', text: '홍콩 K-Beauty 진출', img: imgHongkong },
{ year: '2025', text: '한국 소비자 평가 대상 2연속 수상', img: imgBrand },
]
// 모바일용 — 같은 년도끼리 묶어 "년도(헤더) + 항목 리스트" 형태로 표시 (등장 순서 유지)
const historyGroups = computed(() => {
const groups: { year: string; items: HistoryItem[] }[] = []
for (const item of history) {
const last = groups[groups.length - 1]
if (last && last.year === item.year) last.items.push(item)
else groups.push({ year: item.year, items: [item] })
}
return groups
})
// 구성원 카드 — PEOPLE 섹션 비활성화로 함께 주석 처리 (재활성화 시 아래 + 템플릿 주석 해제)
// interface PeopleCard {
// label: string
// shape: 'tall' | 'wide'
// title: string
// desc: string
// }
// const peopleColA: PeopleCard[] = [
// { label: '회사 사진 — 종무식', shape: 'tall', title: '2025 이너탭 종무식 : “Together, We Rise”', desc: '함께 만든 시간, 더 높이 올라가기 위한 시작' },
// { label: '회사 사진 — 인터뷰', shape: 'wide', title: '꿈은 크게, 실행은 집요하게!', desc: '브랜드사업본부장, 조이' },
// ]
// const peopleColB: PeopleCard[] = [
// { label: '회사 사진 — 구성원', shape: 'wide', title: '2025 Innertab Superookie', desc: '최고의 순간은 함께 만든 성장 속에서 — 슈퍼루키 5인의 성장 스토리' },
// { label: '회사 사진 — 인터뷰', shape: 'tall', title: '실험·회고·학습으로 실제로 팔리는 브랜드를 만듭니다', desc: '글로벌사업본부 영미권실장, Gaby' },
// ]
</script>
<template>
<div>
<AppHeader variant="home" />
<!-- ===================== HERO ===================== -->
<section class="hero">
<!-- 히어로 배경 영상 자동재생/무음/반복(모바일 인라인 재생)
poster: 실제 프레임을 즉시 표시해 로딩 섹션 제거
source 우선순위: WebM(VP9, 작음) MP4(폴백) -->
<video
class="hero-video"
poster="/images/hero2-poster.jpg"
autoplay
muted
loop
playsinline
preload="auto"
>
<source src="/videos/hero2.mp4" type="video/mp4" >
</video>
<div class="scroll-hint"><span>SCROLL</span><i /></div>
</section>
<!-- ===================== ABOUT ===================== -->
<section id="mission" class="about">
<div class="wrap">
<div class="inner">
<p v-reveal="{ delay: 220 }" class="about-eyebrow">누군가의 매일을 낫게 만드는 </p>
<h2 v-reveal="{ delay: 340 }" class="m-title">고객만을 위한 <mark>해답</mark> 제공합니다.</h2>
<p v-reveal="{ delay: 420 }" class="about-intro">
이너탭은 2023년 창립 이후 꾸준히 성장하고 있는 D2C 스타트업입니다.<br >
올리브 캡슐 올베라진, 밀크씨슬 브랜드 리필앤칸 액티브 <br >
다양한 비즈니스로 고객에게 다가가고 있습니다.
</p>
<!-- 미션 / 비전 라벨 + 영문 타이틀 + 국문 설명 (구분선 분리) -->
<dl class="mv-list">
<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: 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>
<p class="mv-desc">우리가 만든 제품이<br >누구나 알만한 브랜드로 거듭나도록 합니다.</p>
</dd>
</div>
</dl>
</div>
<!-- 브랜드 벤토 그리드 -->
<div id="brands" class="brand-bento">
<component
:is="brand.link ? 'a' : 'div'"
v-for="(brand, i) in brands"
:key="brand.name"
v-reveal:scale="{ delay: i * 70 }"
class="btile"
:class="{ feature: brand.feature, 'coming-soon': brand.comingSoon }"
:href="brand.link || undefined"
:target="brand.link ? '_blank' : undefined"
:rel="brand.link ? 'noopener noreferrer' : undefined"
:aria-label="brand.comingSoon ? `${brand.name} 출시예정` : `${brand.name} 바로가기`"
>
<img :src="brand.img" :alt="`${brand.name} 브랜드 이미지`" >
<div class="tile-overlay" />
<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>
</component>
</div>
</div>
</section>
<!-- ===================== GROWTH ===================== -->
<section id="growth" class="growth">
<!-- 배경 영상 히어로와 동일하게 무한 반복 / poster·WebM·MP4 폴백 -->
<div class="growth-bg">
<video
ref="growthVideo"
class="growth-video"
poster="/images/growth-poster.webp"
autoplay
muted
loop
playsinline
preload="auto"
>
<source src="/videos/growth.webm" type="video/webm" >
<source src="/videos/growth-opt.mp4" type="video/mp4" >
</video>
<!-- 라이트 스크림 어두운 텍스트/글래스 카드 가독성 유지 -->
<div class="growth-scrim" />
</div>
<div class="wrap">
<div class="growth-head">
<p v-reveal class="m-eyebrow">Growth</p>
<h2 v-reveal="{ delay: 100 }">우리가 만든 변화를 증명하며,<br >끊임없이 성장하고 있습니다.</h2>
</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 timeline-flat">
<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>
<!-- 모바일: 년도 헤더 하나로 묶고 아래 항목 리스트 나열 -->
<ul class="timeline-grouped">
<li
v-for="(g, gi) in historyGroups"
:key="g.year"
v-reveal="{ delay: 200 + gi * 90 }"
class="tg-group"
>
<span class="tg-year">{{ g.year }}</span>
<ul class="tg-items">
<li v-for="(item, i) in g.items" :key="i" class="tg-item">
<span class="t-text">{{ item.text }}</span>
<img v-if="item.img" :src="item.img" class="t-flag" :alt="`${item.text} 이미지`" >
<span v-else-if="item.label" class="t-label">{{ item.label }}</span>
</li>
</ul>
</li>
</ul>
</div>
</div>
<!-- 하단 : 나머지 지표 3개 나란히 (전체 ) -->
<div class="stat-grid">
<div
v-for="(stat, i) in stats"
:key="stat.title"
v-reveal="{ delay: i * 90 }"
class="gcard stat-card"
>
<div class="stat-orb" />
<div class="gcard-title">{{ stat.title }}</div>
<div class="stat-big">
<CountUp :value="stat.value" /><small>{{ stat.unit }}</small><span class="plus">+</span>
</div>
<p class="stat-desc">
<template v-for="(line, li) in stat.desc.split('\n')" :key="li">
{{ line }}<br v-if="li === 0" >
</template>
</p>
</div>
</div>
</div>
</div>
</section>
<!-- ===================== PEOPLE (비활성화 사이트에서 숨김) ===================== -->
<!--
<section id="people" class="people">
<div class="wrap">
<div class="people-head">
<p v-reveal class="people-lead">이너탭은</p>
<h2 v-reveal="{ delay: 100 }">구성원들과 함께 성장합니다.</h2>
</div>
<div class="people-cols">
<div class="pcol pcol-a">
<article v-for="(card, i) in peopleColA" :key="i" v-reveal="{ delay: i * 120 }" class="pcard">
<div class="pshot" :class="card.shape">
<ImagePlaceholder :label="card.label" />
</div>
<h3>{{ card.title }}</h3>
<p>{{ card.desc }}</p>
</article>
</div>
<div class="pcol pcol-b">
<article v-for="(card, i) in peopleColB" :key="i" v-reveal="{ delay: 80 + i * 120 }" class="pcard">
<div class="pshot" :class="card.shape">
<ImagePlaceholder :label="card.label" />
</div>
<h3>{{ card.title }}</h3>
<p>{{ card.desc }}</p>
</article>
</div>
</div>
</div>
</section>
-->
<!-- ===================== CTA ===================== -->
<section id="cta" class="cta">
<div class="cta-bg" />
<div class="cta-overlay" />
<div class="wrap">
<div class="cta-inner">
<h2 v-reveal>바로 지금,<br >이너탭의 여정에 함께 하세요!</h2>
<p v-reveal="{ delay: 120 }">저희와 함께 성장을 만들어 나갈 구성원을 기다리고 있습니다.</p>
<div v-reveal="{ delay: 240 }" class="cta-btns">
<NuxtLink to="/coffee-chat" class="btn btn-primary">커피챗 신청하기</NuxtLink>
</div>
</div>
</div>
</section>
<AppFooter />
</div>
</template>
<style scoped>
/* ===================== HERO ===================== */
.hero {
position: relative;
overflow: hidden;
/* 헤더(4.5rem)를 제외한 화면 높이를 가득 채움 — dvh로 모바일 주소창 변동 대응 */
height: calc(100dvh - 4.5rem);
/* 영상 로드 전 폴백 배경 — 흰 섹션으로 즉시 표시 */
background: var(--white);
}
.hero-video {
display: block;
width: 100%; /* 가로폭을 꽉 채움 */
height: 100%; /* 섹션 높이(화면-헤더)를 가득 채움 */
object-fit: cover; /* 비율 유지하며 영역을 채우고 넘치는 부분은 크롭 (poster에도 동일 적용) */
/* 로드 시 살짝 확대된 상태에서 천천히 안착 (Ken Burns) */
animation: hero-settle 2.6s cubic-bezier(0.16, 1, 0.3, 1) both;
}
@keyframes hero-settle {
from {
transform: scale(1.12);
}
to {
transform: scale(1);
}
}
@keyframes hero-fade-in {
from {
opacity: 0;
transform: translateY(0.5rem);
}
to {
opacity: 1;
transform: none;
}
}
.scroll-hint {
position: absolute;
bottom: 1.75rem; /* 28px */
right: var(--pad);
z-index: 2;
color: rgba(255, 255, 255, 0.7);
font-size: 0.75rem; /* 12px */
letter-spacing: 0.12em;
text-transform: uppercase;
display: flex;
flex-direction: column;
align-items: center;
gap: 0.625rem; /* 10px */
animation: hero-fade-in 1.2s ease 0.7s both;
}
.scroll-hint span {
writing-mode: vertical-rl;
}
.scroll-hint i {
position: relative;
width: 0.0625rem; /* 1px */
height: 2.875rem; /* 46px */
background: rgba(255, 255, 255, 0.25);
display: block;
overflow: hidden;
}
/* 라인을 따라 아래로 흐르는 펄스 — 스크롤 유도 */
.scroll-hint i::after {
content: '';
position: absolute;
left: 0;
right: 0;
top: -100%;
height: 100%;
background: rgba(255, 255, 255, 0.9);
animation: scroll-pulse 1.8s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}
@keyframes scroll-pulse {
0% {
top: -100%;
}
60%,
100% {
top: 100%;
}
}
/* ===================== ABOUT ===================== */
.about {
padding: clamp(3.5rem, 8.5vw, 7.5rem) 0; /* 56~120px — 세로 간격 축소 */
background: var(--white);
}
.about .inner {
max-width: 100%; /* 사이트 폭(.wrap)에 맞춰 브랜드 벤토와 동일하게 */
margin: 0 auto;
}
.m-eyebrow {
font-size: 1.4375rem; /* 23px */
font-weight: 700;
color: var(--label);
font-family: var(--font-display);
letter-spacing: 0.1em;
}
.about-eyebrow {
font-size: clamp(1rem, 1.7vw, 1.25rem); /* 16~20px */
color: var(--ink-soft);
font-weight: 500;
letter-spacing: -0.01em;
}
.m-title {
font-size: clamp(1.875rem, 4.4vw, 3.375rem); /* 30~54px */
font-weight: 800;
letter-spacing: -0.025em;
line-height: 1.3;
margin-top: 0.875rem; /* 14px */
}
.m-title mark {
background: var(--ink); /* 검은색 하이라이트 */
color: var(--white);
padding: 0.04em 0.14em;
border-radius: 0.125rem; /* 2px */
}
.about-intro {
font-size: clamp(1rem, 1.5vw, 1.1875rem); /* 16~19px */
color: var(--ink-soft);
margin-top: clamp(1.75rem, 3.5vw, 2.75rem); /* 28~44px — 세로 간격 축소 */
}
/* 미션 / 비전 리스트 — 각 행을 상단 구분선으로 분리 */
.mv-list {
margin: clamp(2.5rem, 5vw, 4rem) 0 0; /* 상단 40~64px — 세로 간격 축소 */
}
.mv-content {
margin: 0; /* dd 기본 들여쓰기 제거 */
}
.mv-row {
display: grid;
grid-template-columns: minmax(10rem, 18%) 1fr; /* 라벨 | 내용 */
gap: clamp(1.5rem, 4vw, 4rem);
align-items: start;
padding: clamp(1.5rem, 3vw, 2.25rem) 0; /* 24~36px — 세로 간격 축소 */
border-top: 0.0625rem solid var(--line);
}
.mv-row:last-child {
border-bottom: 0.0625rem solid var(--line);
}
.mv-label {
font-family: var(--font-display);
font-size: clamp(1.75rem, 3vw, 2.5rem); /* 28~40px — 확대 */
font-weight: 700;
letter-spacing: 0.02em;
color: var(--ink);
line-height: 1;
}
.mv-title {
font-size: clamp(1.4375rem, 2.6vw, 2.0625rem); /* 23~33px — 확대 */
font-weight: 800;
letter-spacing: -0.01em;
color: var(--ink);
line-height: 1.3;
}
.mv-desc {
margin-top: 0.875rem; /* 14px */
font-size: clamp(1.0625rem, 1.7vw, 1.3125rem); /* 17~21px — 확대 */
color: var(--ink-soft);
line-height: 1.6;
}
/* ===================== 브랜드 벤토 ===================== */
.brand-bento {
margin-top: clamp(3.5rem, 7vw, 6rem); /* 56~96px */
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: auto;
gap: clamp(0.75rem, 1.4vw, 1.125rem); /* 12~18px */
}
.btile {
position: relative;
display: block;
overflow: hidden;
border-radius: 1.25rem; /* 20px */
aspect-ratio: 1;
background: #11151f;
cursor: pointer; /* 이미지 위에서 포인터 커서 */
text-decoration: none; /* a 태그 밑줄 제거 */
}
/* 출시예정 타일 — 클릭 불가, 기본 커서 */
.btile.coming-soon {
cursor: default;
}
.btile.feature {
/* 가로로 2칸 차지하는 와이드 타일 — 가로(landscape) 이미지가 잘리지 않도록 */
grid-column: span 2;
aspect-ratio: 2 / 1;
}
.btile img {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);
}
.btile:hover img {
transform: scale(1.05); /* 호버 시 이미지 확대 */
}
.btile .tile-overlay {
position: absolute;
inset: 0;
z-index: 2;
pointer-events: none;
background: linear-gradient(to top, rgba(8, 11, 18, 0.78) 0%, rgba(8, 11, 18, 0.25) 34%, transparent 60%);
}
.btile .tile-name {
position: absolute;
left: clamp(1.25rem, 2vw, 1.875rem); /* 20~30px */
bottom: clamp(1.25rem, 2vw, 1.75rem); /* 20~28px */
z-index: 3;
color: #fff;
font-weight: 800;
letter-spacing: 0.01em;
line-height: 1;
/* 표기는 데이터의 원본 대소문자 그대로 — 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);
}
.btile.feature .tile-name {
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 */
bottom: clamp(1rem, 1.6vw, 1.375rem);
z-index: 3;
width: 2.875rem; /* 46px */
height: 2.875rem;
border-radius: 50%;
border: 0.09375rem solid rgba(255, 255, 255, 0.7); /* 1.5px */
color: #fff;
display: grid;
place-items: center;
font-size: 1.0625rem; /* 17px */
pointer-events: none;
transition: background 0.25s ease, color 0.25s ease, transform 0.25s ease;
}
.btile:hover .tile-arrow {
background: #fff;
color: var(--brand);
transform: translateY(-0.125rem);
}
/* 출시예정 배지 */
.btile .tile-badge {
position: absolute;
right: clamp(1rem, 1.6vw, 1.375rem); /* 16~22px */
bottom: clamp(1rem, 1.6vw, 1.375rem);
z-index: 3;
padding: 0.5rem 0.875rem; /* 8~14px */
border-radius: 1.25rem; /* 20px */
border: 0.09375rem solid rgba(255, 255, 255, 0.7); /* 1.5px */
background: rgba(8, 11, 18, 0.35);
color: #fff;
font-size: 0.8125rem; /* 13px */
font-weight: 700;
letter-spacing: 0.02em;
pointer-events: none;
}
/* ===================== GROWTH ===================== */
.growth {
position: relative;
padding: clamp(4.5rem, 11vw, 9.375rem) 0; /* 72~150px */
overflow: hidden;
}
.growth-bg {
position: absolute;
inset: 0;
z-index: 0;
overflow: hidden;
background: #c2c8cd; /* 영상 로드 전 폴백 */
}
.growth-video {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover; /* 섹션 전체를 비율 유지하며 채움 */
}
/* 라이트 스크림 — 영상 위에 실버 톤을 덧입혀 가독성 확보 */
.growth-scrim {
position: absolute;
inset: 0;
background:
radial-gradient(circle at 16% 24%, rgba(255, 255, 255, 0.5), transparent 24%),
radial-gradient(circle at 84% 70%, rgba(255, 255, 255, 0.4), transparent 22%),
linear-gradient(125deg, rgba(190, 196, 201, 0.62) 0%, rgba(210, 215, 220, 0.55) 50%, rgba(186, 193, 199, 0.62) 100%);
}
.growth .wrap {
position: relative;
z-index: 1;
}
.growth-head {
text-align: center;
margin-bottom: clamp(2.5rem, 5vw, 4.375rem); /* 40~70px */
}
.growth-head .m-eyebrow {
margin-bottom: 1.125rem; /* 18px */
}
.growth-head h2 {
font-size: clamp(1.625rem, 4vw, 3.125rem); /* 26~50px — 좁은 화면 시작값 살짝 축소 */
font-weight: 800;
letter-spacing: -0.025em;
line-height: 1.32;
color: var(--ink);
/* 한글이 글자 단위로 끊기지 않고 어절(공백) 단위로만 줄바꿈되도록 */
word-break: keep-all;
text-wrap: balance; /* 여러 줄일 때 줄 길이를 고르게 분배 */
}
/* 세로 스택 — 상단 행(매출+연혁) → 하단 행(지표 3개) */
.growth-layout {
display: flex;
flex-direction: column;
gap: clamp(1rem, 1.8vw, 1.5rem); /* 16~24px */
}
/* 상단 행 — 매출 카드(콘텐츠 폭) + 연혁 카드(남는 폭 채움) */
.growth-top {
display: flex;
gap: clamp(1rem, 1.8vw, 1.5rem);
align-items: stretch; /* 두 카드 높이 맞춤 */
}
.stat-grid {
display: grid;
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%
);
}
/* 2026년으로 올수록 점점 더 커지는 구체 크기 (크기 차이를 뚜렷하게)
※ .orb-cluster를 함께 명시해 .stat-card .stat-orb(동일 폭 일괄 지정)보다
특이도를 높여 구체별 폭이 확실히 적용되도록 함 */
.revenue-card .orb-cluster .orb-1 {
width: clamp(4.75rem, 8.5vw, 7rem);
opacity: 0.5; /* 가장 옅게 */
}
.revenue-card .orb-cluster .orb-2 {
width: clamp(7.5rem, 14vw, 11.5rem);
opacity: 0.74;
margin-left: clamp(-2.5rem, -4vw, -3.25rem); /* 앞 구체와 겹침 */
}
/* 마지막 구체 — 가장 크고 기존 단일 구체와 동일한 불투명도(opacity 미지정 = 1)
DOM 순서상 뒤에 있어 위에 그려지며 가장 진하게 앞으로 옴 */
.revenue-card .orb-cluster .orb-3 {
width: clamp(11.5rem, 21vw, 17.5rem);
margin-left: clamp(-3.5rem, -6vw, -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;
letter-spacing: -0.01em;
margin-bottom: 0.25em;
}
/* 연도 텍스트도 구체 크기에 맞춰 2026년으로 갈수록 점점 더 크게 */
.revenue-card .orb-1 .orb-year {
font-size: clamp(0.6875rem, 1.1vw, 0.875rem); /* 11~14px */
}
.revenue-card .orb-2 .orb-year {
font-size: clamp(0.8125rem, 1.3vw, 1.0625rem); /* 13~17px */
}
.revenue-card .orb-3 .orb-year {
font-size: clamp(0.9375rem, 1.6vw, 1.25rem); /* 15~20px */
}
.revenue-card .orb-value {
font-weight: 800;
letter-spacing: -0.03em;
white-space: nowrap;
}
/* 숫자 크기도 구체 크기에 맞춰 2026년으로 갈수록 점점 더 크게 확대 */
.revenue-card .orb-1 .orb-value {
font-size: clamp(1.125rem, 2.1vw, 1.625rem); /* 18~26px */
}
.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.625rem, 5.4vw, 4.25rem); /* 42~68px */
}
/* 단위(억) — 숫자보다 작게 */
.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);
backdrop-filter: blur(0.375rem) saturate(1.1);
-webkit-backdrop-filter: blur(0.375rem) saturate(1.1);
border: 0.0625rem solid rgba(255, 255, 255, 0.5);
border-radius: 1.5rem; /* 24px */
padding: clamp(1.625rem, 2.6vw, 2.375rem); /* 26~38px */
box-shadow: 0 1.25rem 3.125rem -2.125rem rgba(30, 40, 60, 0.5);
overflow: hidden;
}
.gcard-title,
.stat-big,
.stat-desc,
.history-slogan,
.timeline {
position: relative;
z-index: 1;
}
.stat-card {
display: flex;
flex-direction: column;
}
.stat-card .stat-orb {
position: absolute;
z-index: 0;
width: clamp(9.375rem, 17vw, 12.5rem); /* 150~200px */
aspect-ratio: 1;
border-radius: 50%;
left: 1rem; /* 16px — 카드 안쪽으로 이동 */
top: 3.75rem; /* 60px */
/* 가장자리를 투명하게 → 하드한 동그라미 테두리 제거 */
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%
);
}
.gcard-title {
font-size: 1.0625rem; /* 17px */
font-weight: 700;
color: var(--ink);
}
.stat-card .stat-big {
font-size: clamp(2.5rem, 5vw, 3.75rem); /* 40~60px */
font-weight: 800;
letter-spacing: -0.03em;
color: var(--ink);
line-height: 1;
margin: clamp(1.75rem, 4vw, 3rem) 0 clamp(1.25rem, 3vw, 1.875rem);
}
.stat-card .stat-big small {
font-size: 0.36em;
font-weight: 700;
margin-left: 0.1875rem; /* 3px */
letter-spacing: 0;
}
.plus {
display: inline-grid;
place-items: center;
width: 1.125rem; /* 18px */
height: 1.125rem;
border-radius: 50%;
background: var(--brand);
color: #fff;
font-size: 0.6875rem; /* 11px */
font-weight: 700;
vertical-align: top;
margin-left: 0.25rem; /* 4px */
}
.stat-card .stat-desc {
font-size: 0.875rem; /* 14px */
color: var(--ink-soft);
line-height: 1.65;
margin-top: auto;
}
.history-card {
display: flex;
flex-direction: column;
flex: 1 1 0; /* 매출 카드 옆 남는 폭을 모두 채움 */
min-width: 0;
}
/* 연혁 슬로건 — 제목 아래 메시지 */
.history-slogan {
margin-top: 0.5rem; /* 8px */
font-size: 0.875rem; /* 14px */
font-weight: 600;
color: var(--brand);
letter-spacing: -0.01em;
}
.timeline {
list-style: none;
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: center; /* 텍스트와 이미지를 세로 중앙 정렬 */
padding: 0; /* 행 상하 여백 제거 */
min-height: clamp(2.625rem, 3.9vw, 3.375rem); /* 이미지 높이와 동일 — 이미지 없는 행도 균일 */
border-top: 0.0625rem solid rgba(40, 50, 70, 0.1);
}
.timeline li:first-child {
border-top: 0;
}
/* 년도 표기 — 좌측 고정 폭, 브랜드 컬러 강조 */
.timeline .t-year {
flex: none;
width: 2.875rem; /* 46px */
font-family: var(--font-display);
font-size: 1.0625rem; /* 17px */
font-weight: 700;
letter-spacing: 0.02em;
color: var(--brand);
line-height: 1.4;
}
.timeline .t-text {
font-size: 0.9375rem; /* 15px */
color: var(--ink);
font-weight: 500;
line-height: 1.4;
}
/* 행 오른쪽 끝 이미지 — 비율이 달라도 동일한 정사각 박스로 통일 */
.timeline .t-flag {
flex: none;
margin-left: auto; /* 우측 끝단으로 밀착 */
align-self: center;
width: clamp(1.8375rem, 2.73vw, 2.3625rem); /* 약 29~38px — 직전 대비 70% 축소 */
height: clamp(1.8375rem, 2.73vw, 2.3625rem);
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(--ink); /* 검은색 */
line-height: 1;
}
/* ===== 모바일 연혁 — 년도 묶음 형태 (기본 숨김, 모바일에서만 표시) ===== */
.timeline-grouped {
display: none; /* 데스크톱에서는 .timeline-flat 사용 */
list-style: none;
margin-top: clamp(1.25rem, 2.5vw, 1.875rem);
}
/* 년도 그룹 — 상단 구분선 + 상하 여백 */
.timeline-grouped .tg-group {
padding: 0.875rem 0; /* 14px */
border-top: 0.0625rem solid rgba(40, 50, 70, 0.1);
}
.timeline-grouped .tg-group:first-child {
border-top: 0;
padding-top: 0;
}
/* 년도 헤더 — 그룹당 한 번만 표기 */
.timeline-grouped .tg-year {
display: block;
font-family: var(--font-display);
font-size: 1.125rem; /* 18px */
font-weight: 700;
letter-spacing: 0.02em;
color: var(--brand);
margin-bottom: 0.625rem; /* 10px — 헤더↔리스트 간격 */
}
/* 그룹 내 항목 리스트 */
.timeline-grouped .tg-items {
list-style: none;
display: flex;
flex-direction: column;
gap: 0.625rem; /* 10px */
}
.timeline-grouped .tg-item {
display: flex;
align-items: center;
gap: 0.75rem; /* 12px */
}
.timeline-grouped .tg-item .t-text {
flex: 1; /* 텍스트가 남는 폭 차지 → 이미지/배지는 우측 끝 */
font-size: 0.9375rem; /* 15px */
color: var(--ink);
font-weight: 500;
line-height: 1.4;
}
/* 그룹 항목의 우측 이미지/배지 — 데스크톱 timeline과 동일 규칙 */
.timeline-grouped .t-flag {
flex: none;
margin-left: auto;
width: clamp(1.8375rem, 2.73vw, 2.3625rem);
height: clamp(1.8375rem, 2.73vw, 2.3625rem);
border-radius: 0.25rem;
object-fit: contain;
}
.timeline-grouped .t-label {
flex: none;
margin-left: auto;
font-family: var(--font-display);
font-weight: 700;
font-size: 1.25rem; /* 20px */
letter-spacing: 0.04em;
color: var(--ink);
line-height: 1;
}
/* ===================== PEOPLE ===================== */
.people {
padding: clamp(4.5rem, 11vw, 9.375rem) 0; /* 72~150px */
}
.people-lead {
font-size: clamp(1.125rem, 1.9vw, 1.5rem); /* 18~24px */
font-weight: 700;
color: var(--ink);
letter-spacing: -0.01em;
}
.people-head h2 {
font-size: clamp(1.875rem, 4.4vw, 3.5rem); /* 30~56px */
font-weight: 800;
letter-spacing: -0.025em;
line-height: 1.18;
color: var(--ink);
margin-top: 0.625rem; /* 10px */
}
.people-cols {
display: grid;
grid-template-columns: 1fr 1fr;
gap: clamp(1.5rem, 2.6vw, 2.75rem); /* 24~44px */
margin-top: clamp(2.25rem, 4.5vw, 3.75rem); /* 36~60px */
align-items: start;
}
.pcol {
display: flex;
flex-direction: column;
gap: clamp(2.5rem, 5vw, 4.5rem); /* 40~72px */
}
.pcol-b {
margin-top: clamp(3rem, 7vw, 6.5rem); /* 48~104px */
}
.pcard {
cursor: pointer;
}
.pcard .pshot {
position: relative;
width: 100%;
border-radius: 1rem; /* 16px */
overflow: hidden;
background: #edeff2;
transition: box-shadow 0.3s ease, transform 0.3s ease;
}
.pcard .pshot.tall {
aspect-ratio: 4 / 5;
}
.pcard .pshot.wide {
aspect-ratio: 4 / 3;
}
.pcard:hover .pshot {
box-shadow: 0 1.625rem 3.5rem -2rem rgba(30, 40, 60, 0.5);
transform: translateY(-0.25rem); /* -4px */
}
.pcard h3 {
font-size: clamp(1.125rem, 1.7vw, 1.375rem); /* 18~22px */
font-weight: 700;
letter-spacing: -0.01em;
color: var(--ink);
margin-top: 1.25rem; /* 20px */
line-height: 1.4;
}
.pcard p {
font-size: clamp(0.8125rem, 1.2vw, 0.9375rem); /* 13~15px */
color: var(--ink-soft);
margin-top: 0.5rem; /* 8px */
line-height: 1.55;
}
/* ===================== CTA ===================== */
.cta {
position: relative;
overflow: hidden;
padding: clamp(4.5rem, 10vw, 8rem) 0; /* 72~128px — 높이 축소 */
}
.cta-bg {
position: absolute;
inset: 0;
z-index: 0;
/* 배너 이미지 배경 */
background: url('/images/img-banner.png') center / cover no-repeat;
}
.cta-overlay {
position: absolute;
inset: 0;
z-index: 1;
/* 더 어둡게 */
background: linear-gradient(90deg, rgba(16, 13, 9, 0.82) 0%, rgba(16, 13, 9, 0.7) 60%, rgba(16, 13, 9, 0.6) 100%);
}
.cta .wrap {
position: relative;
z-index: 2;
}
.cta-inner {
color: var(--white);
max-width: 45rem; /* 720px */
}
.cta-inner h2 {
font-size: clamp(1.75rem, 4.2vw, 3.25rem); /* 28~52px */
font-weight: 800;
letter-spacing: -0.02em;
line-height: 1.2;
}
.cta-inner p {
color: rgba(255, 255, 255, 0.82);
font-size: clamp(0.9375rem, 1.5vw, 1.125rem); /* 15~18px */
margin-top: 1.125rem; /* 18px */
}
.cta-btns {
display: flex;
gap: 0.875rem; /* 14px */
margin-top: clamp(2rem, 4vw, 3rem); /* 32~48px */
flex-wrap: wrap;
}
/* ===================== 반응형 ===================== */
@media (max-width: 56.25rem) {
/* 900px */
/* 상단 행: 좁은 화면에서는 매출/연혁 카드를 세로로 쌓고 전체 폭 사용 */
.growth-top {
flex-direction: column;
}
/* 세로로 쌓일 때 두 카드 모두 콘텐츠 높이를 갖도록.
history-card의 flex:1 1 0(=flex-basis 0)이 세로 스택에서 높이 0으로
눌려 연혁 표가 보이지 않던 문제를 해결한다. */
.revenue-card,
.history-card {
flex: 0 0 auto;
}
/* 연혁 타임라인 — 세로 스택에서는 균등 채움(flex:1) 대신 콘텐츠 높이 사용 */
.timeline {
flex: 0 0 auto;
}
.brand-bento {
grid-template-columns: 1fr 1fr;
}
.btile.feature {
grid-row: auto;
grid-column: span 2;
aspect-ratio: 16 / 10;
}
/* 미션/비전: 좁은 화면에서는 라벨을 내용 위로 쌓음 */
.mv-row {
grid-template-columns: 1fr;
gap: 0.875rem; /* 14px */
}
}
@media (max-width: 32.5rem) {
/* 520px */
.brand-bento {
grid-template-columns: 1fr;
}
.btile.feature {
grid-column: auto;
aspect-ratio: 1; /* 1열에서는 다른 타일과 동일한 정사각 비율 */
}
/* Growth 스탯: 가장 작은 화면에서는 2x2 → 1열 나열 */
.stat-grid {
grid-template-columns: 1fr;
}
/* 연혁: 모바일에서는 행별 년도(평면) 대신 년도 묶음 형태로 전환 */
.timeline-flat {
display: none;
}
.timeline-grouped {
display: block;
}
/* 연 매출 성장률 구체 — 모바일에서는 3개 크기 차이를 줄이고(1 : 1.29 : 1.57)
전체적으로 축소해 카드 안에 균형 있게 배치 */
.revenue-card .orb-cluster .orb-1 {
width: 5.25rem; /* 84px */
}
.revenue-card .orb-cluster .orb-2 {
width: 6.75rem; /* 108px */
margin-left: -1.5rem;
}
.revenue-card .orb-cluster .orb-3 {
width: 8.25rem; /* 132px */
margin-left: -1.75rem;
}
/* 구체 내부 숫자도 작아진 구체 크기에 맞춰 축소 */
.revenue-card .orb-1 .orb-value {
font-size: 1.125rem; /* 18px */
}
.revenue-card .orb-2 .orb-value {
font-size: 1.5rem; /* 24px */
}
.revenue-card .orb-3 .orb-value {
font-size: 2rem; /* 32px */
}
.people-cols {
grid-template-columns: 1fr;
gap: clamp(2.5rem, 8vw, 4rem);
}
.pcol {
gap: clamp(2.5rem, 8vw, 4rem);
}
.pcol-b {
margin-top: 0;
}
.pcard .pshot.tall,
.pcard .pshot.wide {
aspect-ratio: 4 / 3;
}
}
/* 모션 최소화 선호 시 히어로/호버 애니메이션 비활성화 */
@media (prefers-reduced-motion: reduce) {
.hero-video,
.scroll-hint,
.scroll-hint i::after {
animation: none !important;
}
.btile img {
transition: none;
}
.btile:hover img {
transform: none;
}
}
</style>