카피
- 데모 섹션 헤드라인: "직접 협상해 보세요 / 에이전트는 정해진 기준을 벗어나지 않습니다"
→ "사용할수록 진화하는 에이전틱 협상, / 직접 경험해 보세요!"
예전 카피는 FAQ 2번("에이전트가 우리 기준을 벗어나 합의해 버리면요?")을 헤드라인으로
끌어올린 것이었다. 아직 생기지도 않은 반론에 가장 비싼 한 줄을 쓰고 있었고,
부정문이라 "안 하는 일"을 약속했다 — 체험을 권하는 자리에 맞지 않는다.
방어는 FAQ 에 그대로 남아 있다.
- 히어로 1차 CTA: "직접 협상해 보기" → "여기서 직접 체험"
- 히어로 2차 CTA: "도입 문의" → "데모 요청". 기존엔 #contact-section 으로 가서
GNB "상담 신청" 과 목적지가 같았다 — 버튼만 둘이고 경로는 하나였다.
리드 캡처
- DemoRequestModal 신규. 이름·이메일 두 칸만 받는다. 필드가 늘수록 이탈이 늘고,
영업 첫 연락에 필요한 최소가 그 둘이다. 나머지는 통화에서 채운다.
- 모달로 띄우는 이유: 히어로에서 관심이 생긴 자리에서 받아야 한다. 스크롤로
내려보내면 그 사이에 식는다. 고관여 폼(상담 신청)은 그대로 두고 그 앞단을 만든 것.
- 접근성: Esc 닫기, Tab 을 모달 안에 가둠, 열릴 때 첫 필드 포커스·닫힐 때 복원,
aria-modal/labelledby, 배경 스크롤 잠금, prefers-reduced-motion 대응.
전송 경로 — 성공을 위조하지 않는다
contact.tsx 는 1.2초 뒤 성공 화면만 띄우고 아무 데도 보내지 않는다("백엔드 미연결").
리드 제너레이션에서 그 방식은 최악이다. 화면은 접수됐다고 하는데 영업이 받을 리드는
없고, 아무도 그 사실을 모른다. 그래서 lib/lead.ts 는 VITE_LEAD_ENDPOINT 가 없으면
not-configured 를 돌려주고, 모달은 그걸 실패로 처리해 상담 신청 경로를 안내한다.
⚠️ VITE_LEAD_ENDPOINT 를 설정하기 전까지 데모 요청은 저장되지 않는다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
35 lines
1.7 KiB
TypeScript
35 lines
1.7 KiB
TypeScript
import * as React from "react"
|
|
|
|
import { cn } from "@/lib/utils"
|
|
|
|
/*
|
|
* 문의 폼 필드.
|
|
*
|
|
* 회색 채움 박스는 어느 템플릿에나 있다. 밑줄 필드로 바꾸면 같은 기능인데 훨씬
|
|
* 정돈돼 보인다 — 폼이 "입력 상자 더미"가 아니라 한 장의 문서처럼 읽힌다.
|
|
*
|
|
* 밑줄 폼의 알려진 위험은 입력란으로 안 보이는 것(어포던스 손실)인데,
|
|
* 라벨을 항상 위에 두고 밑줄을 2px 로 두껍게 잡아 보완했다.
|
|
* 두께를 항상 2px 로 고정해서 포커스 때 레이아웃이 흔들리지 않는다.
|
|
*
|
|
* 글자 16px 은 취향이 아니라 필수다 — iOS 사파리는 16px 미만 입력에 포커스하면
|
|
* 화면을 자동 확대해서, 광고로 들어온 모바일 사용자의 폼 이탈을 만든다.
|
|
*/
|
|
const fieldClass =
|
|
"w-full bg-transparent border-0 border-b-2 border-line-strong rounded-none px-0 py-3 " +
|
|
"text-[16px] font-normal text-ink placeholder:text-ink-faint placeholder:font-normal " +
|
|
"outline-none transition-colors hover:border-ink-muted focus:border-primary " +
|
|
"disabled:opacity-50 disabled:cursor-not-allowed"
|
|
|
|
/* ComponentPropsWithRef 로 두면 ref 가 그대로 전달된다 (React 19 는 forwardRef 불필요).
|
|
데모 요청 모달이 열릴 때 첫 필드로 포커스를 옮기려면 ref 가 필요하다. */
|
|
function Input({ className, ...props }: React.ComponentPropsWithRef<"input">) {
|
|
return <input className={cn(fieldClass, className)} {...props} />
|
|
}
|
|
|
|
function Textarea({ className, ...props }: React.ComponentPropsWithRef<"textarea">) {
|
|
return <textarea className={cn(fieldClass, "resize-none leading-[1.6]", className)} {...props} />
|
|
}
|
|
|
|
export { Input, Textarea }
|