[feat] solution/frontend: 히어로 문구 여섯으로 · 보조 문구 제거 — 세로로 퍼지던 걸 줄인다

앞말이 넷이라 금방 반복됐고, 그 아래 보조 문구 세 줄이 히어로를 세로로 늘려 임팩트를 깎았다.

- 앞말 6개: SEO · AEO 최적화 / AI가 먼저 찾는 / 챗GPT가 인용하는 / 검색에 바로 걸리는 /
  손님이 먼저 만나는 / 우리 가게가 직접 말하는
- ★ 문구 개수와 index.css 의 o2o-rotate-6 키프레임은 한 몸이다. 늘리면 stop 도 고쳐야 한다 —
  안 고치면 뒤쪽이 영영 안 보이거나 빈 줄이 지나간다
- 보조 문구 3줄 삭제, 제목 sm:text-6xl 로 키우고 세로 여백 축소
This commit is contained in:
Mina Choi 2026-09-03 10:53:41 +09:00
parent d5e9b87e3f
commit d8ed0766d6
3 changed files with 32 additions and 32 deletions

View File

@ -130,7 +130,7 @@ export function ShowcasePeeks({limit = 10}: {limit?: number}) {
return ( return (
<div <div
className="o2o-marquee relative mt-12 overflow-hidden [mask-image:linear-gradient(90deg,transparent,#000_8%,#000_92%,transparent)]" className="o2o-marquee relative mt-10 overflow-hidden [mask-image:linear-gradient(90deg,transparent,#000_8%,#000_92%,transparent)]"
aria-label="발행된 홈페이지" aria-label="발행된 홈페이지"
> >
<div <div

View File

@ -77,15 +77,19 @@ body {
} }
/* 히어로 제목의 앞말만 갈아 끼운다 — '홈페이지' 는 고정이고 수식어가 돈다. /* 히어로 제목의 앞말만 갈아 끼운다 — '홈페이지' 는 고정이고 수식어가 돈다.
★ CSS 만으로 돈다(마퀴와 같은 이유). 그리고 **문구를 다섯 줄 쌓는다** — 마지막 줄이 ★ CSS 만으로 돈다(마퀴와 같은 이유). 문구를 **일곱 줄** 쌓는다 — 마지막 줄이 첫 줄의
첫 줄의 복제라 -80% 에서 0% 로 되감을 때 글자가 튀지 않는다. 복제라 -85.714% 에서 0% 로 되감을 때 글자가 튀지 않는다.
★ 줄 높이를 1.25em 으로 못 박는다. 창이 1줄이고 트랙이 5줄이라 한 칸이 정확히 20% 여야 한다. */ ★ 줄 높이를 1.25em 으로 못 박는다. 창이 1줄이고 트랙이 7줄이라 한 칸이 정확히 1/7 이어야 한다.
@keyframes o2o-rotate-5 { ★ 문구 개수(6)와 이 키프레임은 한 몸이다. 문구를 늘리면 여기 stop 도 같이 고쳐야 한다 —
0%, 18% { transform: translateY(0); } 안 고치면 마지막 몇 개가 영영 안 보이거나 빈 줄이 지나간다(LandingPage HEADLINES). */
20%, 38% { transform: translateY(-20%); } @keyframes o2o-rotate-6 {
40%, 58% { transform: translateY(-40%); } 0%, 14% { transform: translateY(0); }
60%, 78% { transform: translateY(-60%); } 16.67%, 30.67% { transform: translateY(-14.286%); }
80%, 100% { transform: translateY(-80%); } 33.33%, 47.33% { transform: translateY(-28.571%); }
50%, 64% { transform: translateY(-42.857%); }
66.67%, 80.67% { transform: translateY(-57.143%); }
83.33%, 97.33% { transform: translateY(-71.429%); }
100% { transform: translateY(-85.714%); }
} }
.o2o-rotator { .o2o-rotator {
display: block; display: block;
@ -93,7 +97,7 @@ body {
overflow: hidden; overflow: hidden;
} }
.o2o-rotator-track { .o2o-rotator-track {
animation: o2o-rotate-5 11s cubic-bezier(0.65, 0, 0.35, 1) infinite; animation: o2o-rotate-6 16s cubic-bezier(0.65, 0, 0.35, 1) infinite;
} }
.o2o-rotator-track > span { .o2o-rotator-track > span {
display: block; display: block;

View File

@ -7,10 +7,18 @@ import {ShowcaseGrid, ShowcasePeeks} from '@/features/marketing/ShowcaseGrid';
import {Button} from '@/components/ui/button'; import {Button} from '@/components/ui/button';
/** /**
* 히어로 제목의 앞말. '홈페이지' 는 고정이고 이 넷이 돌아간다. * 히어로 제목의 앞말. '홈페이지' 는 고정이고 이 여섯이 돌아간다.
* ★ 넷을 넘기지 않는다 — 다섯째부터는 한 바퀴 도는 데 걸리는 시간이 체류 시간을 넘긴다. * ★ 개수를 바꾸면 index.css 의 `o2o-rotate-6` 키프레임도 같이 고쳐야 한다 —
* 안 고치면 뒤쪽 문구가 영영 안 보이거나 빈 줄이 지나간다. 조용히 틀리는 종류다.
*/ */
const HEADLINES = ['AI가 먼저 찾는', '챗GPT가 인용하는', '검색에 바로 걸리는', '손님이 먼저 만나는']; const HEADLINES = [
'SEO · AEO 최적화',
'AI가 먼저 찾는',
'챗GPT가 인용하는',
'검색에 바로 걸리는',
'손님이 먼저 만나는',
'우리 가게가 직접 말하는',
];
const INDUSTRIES: {id: IndustryType; label: string; icon: typeof Building2}[] = [ const INDUSTRIES: {id: IndustryType; label: string; icon: typeof Building2}[] = [
{id: 'stay', label: '숙박', icon: Building2}, {id: 'stay', label: '숙박', icon: Building2},
@ -48,8 +56,8 @@ export function LandingPage() {
<MarketingShell> <MarketingShell>
{/* ── 상단 ─────────────────────────────────────── */} {/* ── 상단 ─────────────────────────────────────── */}
<section className="border-b border-border"> <section className="border-b border-border">
<div className="mx-auto w-full max-w-6xl px-5 py-20 text-center sm:py-28"> <div className="mx-auto w-full max-w-6xl px-5 py-16 text-center sm:py-20">
<h1 className="mx-auto max-w-3xl text-3xl leading-[1.25] font-bold tracking-tight sm:text-5xl"> <h1 className="mx-auto max-w-4xl text-4xl leading-[1.25] font-bold tracking-[-0.04em] sm:text-6xl">
{/* 앞말만 돈다. 마지막 항목은 첫 항목의 복제다 — 되감을 때 글자가 튀지 않게(index.css). */} {/* 앞말만 돈다. 마지막 항목은 첫 항목의 복제다 — 되감을 때 글자가 튀지 않게(index.css). */}
<span className="o2o-rotator"> <span className="o2o-rotator">
<span className="o2o-rotator-track"> <span className="o2o-rotator-track">
@ -62,11 +70,11 @@ export function LandingPage() {
</span> </span>
홈페이지 홈페이지
</h1> </h1>
<p className="mx-auto mt-5 max-w-xl text-sm leading-relaxed text-muted-foreground sm:text-base"> <p className="mx-auto mt-4 max-w-xl text-sm text-muted-foreground sm:text-base">
가게 이름 한 줄로 시작해 보세요 가게 이름 한 줄로 시작해 보세요
</p> </p>
<form onSubmit={submit} className="mx-auto mt-9 flex max-w-lg gap-2"> <form onSubmit={submit} className="mx-auto mt-8 flex max-w-lg gap-2">
<div className="relative flex-1"> <div className="relative flex-1">
<Search <Search
className="pointer-events-none absolute top-1/2 left-4 size-4 -translate-y-1/2 text-muted-foreground" className="pointer-events-none absolute top-1/2 left-4 size-4 -translate-y-1/2 text-muted-foreground"
@ -86,7 +94,7 @@ export function LandingPage() {
</form> </form>
{/* 업종은 고르지 않아도 된다 — 여기 있는 건 "누구를 위한 서비스인가" 를 말하기 위한 것이다. */} {/* 업종은 고르지 않아도 된다 — 여기 있는 건 "누구를 위한 서비스인가" 를 말하기 위한 것이다. */}
<div className="mt-6 flex flex-wrap items-center justify-center gap-2"> <div className="mt-4 flex flex-wrap items-center justify-center gap-2">
{INDUSTRIES.map(({id, label, icon: Icon}) => ( {INDUSTRIES.map(({id, label, icon: Icon}) => (
<Link <Link
key={id} key={id}
@ -99,20 +107,8 @@ export function LandingPage() {
))} ))}
</div> </div>
<ul className="mt-8 flex flex-wrap items-center justify-center gap-x-6 gap-y-2 text-xs text-muted-foreground">
{[
'SEO · AEO 자동 적용',
'가입 없이 만들어 봅니다',
'5분이면 끝납니다',
].map((line) => (
<li key={line} className="flex items-center gap-1.5">
<Check className="size-3.5 text-success" aria-hidden />
{line}
</li>
))}
</ul>
{/* 입력칸만 있으면 무엇이 나오는지 알 수 없다 — 결과물 두 장을 먼저 보여준다. */} {/* 입력칸만 있으면 무엇이 나오는지 알 수 없다 — 결과물을 바로 밑에서 흘린다. */}
<ShowcasePeeks /> <ShowcasePeeks />
</div> </div>
</section> </section>