썰박스를 ADO2 디자인 시스템으로 맞추고, 포스터 파이프라인 두 종을 파이프라인
탭에 추가한다. 탭이 4개가 되면서 진입 화면 네비게이션도 함께 손봤다.
## 썰박스 DS 통일
시나리오별 팔레트(조선=파랑·삼국지=빨강·그리스=녹·오디세이=청)와 이모지, 앰버
강조색(--color-ssul-accent)을 걷어냈다. 선택 표시는 castad 표준 문법(민트 테두리
+ 민트 틴트), 스피너는 퍼플, CTA는 퍼플 단색으로 통일했다. 색으로 구분하던 것을
없앤 대신 상태(선택)만 색으로 남긴다.
## Poster to Video 통합 (내부 시연 범위)
- 무빙 포스터(F1): 업로드 → 분석 → **검수 게이트** → 생성 → 완성 5단계 위저드.
검수에서 나레이션·모션·메타태그를 포스터와 대조해 고치고 승인해야 렌더가 이어진다.
- 포스터 스타일링(F2): 위저드가 아닌 한 화면 도구. 여러 스타일을 갈아 끼우며
비교하는 작업이라 단계를 나누면 왕복만 늘어난다.
P2V 서버(:8010)를 castad 백엔드가 아니라 **직접 호출**한다. 검증된 scripts를
subprocess로 감싼 단일 워커라 castad 백엔드에 흡수하려면 실행 환경(Higgsfield
CLI·ffmpeg·모델 키)을 통째로 이식해야 하기 때문이다. 호출은 utils/p2vApi.ts 한
파일에 격리했다 — 대외 공개 시 castad 백엔드에 /p2v/* 프록시를 세우고 카카오 인증·
크레딧 차감을 얹을 때 갈아끼울 지점이 여기 하나다.
인증은 단일 팀 키(P2V_ACCESS_KEY)다. 다른 오리진이라 쿠키가 실리지 않아 정적
산출물(영상·이미지·다운로드)은 p2vFile()이 ?key= 로 태운다.
F2는 영화 포스터 레퍼런스가 저작권 자산이라 **결과물의 외부 공개·상업 사용을
금한다**(퍼블릭 도메인 명화 제외). 화면 상단 고지 + 템플릿별 배포 등급 배지 +
내부 전용을 고른 순간에만 뜨는 경고로 표시한다.
## 진입 화면 네비게이션
- 밑줄 탭 → 아이콘 타일 + 기능명. 탭이 4개가 되자 "무빙 포스터"와 "포스터 스타일링"이
글자로는 갈라지지 않아, 형태로 구분되게 했다. 아이콘은 ADO2 Design System 규칙
(24×24 · fill none · stroke currentColor 2 · round)을 따르고 색은 넣지 않는다.
- 고른 기능의 한 줄 설명을 탭 아래에 붙였다.
- 간격 체계를 8px 그리드로 다시 잡았다(묶음 안 8~12 / 묶음 사이 20 / 섹션 28~32).
이전에는 전부 10~24px이라 근접성으로 구조가 읽히지 않아 답답했다. 타일 간격은
터치 타겟 최소 8dp를 지킨다.
## 버그 수정
- 진입 화면 세로 넘침 잘림: justify-content:center + overflow:hidden 조합이라
콘텐츠가 길어지면 위로 넘친 부분에 스크롤로도 닿을 수 없었다(무빙 포스터에서
로고 밴드 47px 잘림). 자식의 margin:auto 0 중앙정렬로 바꿔 해소.
- 사라진 P2V 잡: 404를 문구가 아니라 상태 코드로 판정한다(P2vNotFoundError).
서버에서 지워진 잡 ID가 남으면 빈 진행 화면에서 멈췄다.
- 검수 화면 모바일: 좌우 여백 0(부모 위저드 컨테이너에 패딩이 없다) → 16px 부여.
대조할 포스터를 편집 위로 올리고, 승인 CTA를 하단 탭바 위에 sticky로 고정.
- 한글 단어 중간 줄바꿈("애니메이/션") → word-break: keep-all.
- 입력·안내·제출 박스 높이를 48px로 통일.
## 카피
가게→업체, 크롤링→수집으로 어휘 통일.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
192 lines
6.8 KiB
HTML
Executable File
192 lines
6.8 KiB
HTML
Executable File
|
|
<!DOCTYPE html>
|
|
<html lang="ko">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
|
<title>ADO2</title>
|
|
<!-- ① 페이지 설명 -->
|
|
<meta name="description" content="ADO2는 ㈜에이아이오투오의 AI 기반 마케팅 자동화 플랫폼입니다. 콘텐츠 제작부터 채널 배포까지 자동으로 처리합니다." />
|
|
<!-- ② Open Graph 제목 -->
|
|
<meta property="og:title" content="ADO2 - AI 마케팅 자동화 플랫폼" />
|
|
<!-- ③ Open Graph 설명 -->
|
|
<meta property="og:description" content="ADO2는 ㈜에이아이오투오의 AI 기반 마케팅 자동화 플랫폼입니다. 콘텐츠 제작부터 채널 배포까지 자동으로 처리합니다." />
|
|
<meta property="og:url" content="https://ado2.o2osolution.ai" />
|
|
<meta property="og:type" content="website" />
|
|
<link rel="icon" type="image/svg+xml" href="/favicon_32.svg" sizes="32x32">
|
|
<link rel="icon" type="image/svg+xml" href="/favicon_48.svg" sizes="48x48">
|
|
<!-- Meta Pixel Code -->
|
|
<script>
|
|
!function(f,b,e,v,n,t,s)
|
|
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
|
|
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
|
|
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
|
|
n.queue=[];t=b.createElement(e);t.async=!0;
|
|
t.src=v;s=b.getElementsByTagName(e)[0];
|
|
s.parentNode.insertBefore(t,s)}(window, document,'script',
|
|
'https://connect.facebook.net/en_US/fbevents.js');
|
|
fbq('init', '1572679738203392');
|
|
fbq('track', 'PageView');
|
|
</script>
|
|
<!-- End Meta Pixel Code -->
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<script>
|
|
tailwind.config = {
|
|
theme: {
|
|
extend: {
|
|
colors: {
|
|
brand: {
|
|
bg: '#001a1c',
|
|
card: '#003538',
|
|
cardHover: '#004548',
|
|
accent: '#a6ffea',
|
|
purple: '#a682ff',
|
|
purpleHover: '#9570f0',
|
|
text: '#d1d5db',
|
|
muted: '#9ca3af'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
<script src="https://t1.kakaocdn.net/kakao_js_sdk/2.7.4/kakao.min.js" crossorigin="anonymous"></script>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,700;1,700&display=swap" rel="stylesheet">
|
|
<link href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/static/pretendard.min.css" rel="stylesheet">
|
|
<style>
|
|
:root {
|
|
--app-height: 100%;
|
|
}
|
|
html, body {
|
|
margin: 0;
|
|
padding: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background-color: #001a1c;
|
|
}
|
|
body {
|
|
font-family: 'Pretendard', 'Apple SD Gothic Neo', -apple-system, BlinkMacSystemFont,
|
|
'Helvetica Neue', 'Segoe UI', system-ui, sans-serif;
|
|
-webkit-font-smoothing: antialiased;
|
|
letter-spacing: -0.006em;
|
|
}
|
|
.font-serif-logo {
|
|
font-family: 'Playfair Display', serif;
|
|
}
|
|
/* Full-page snap scroll container */
|
|
.snap-container {
|
|
height: 100dvh;
|
|
width: 100%;
|
|
overflow-y: auto;
|
|
scroll-snap-type: y mandatory;
|
|
scroll-behavior: smooth;
|
|
-webkit-overflow-scrolling: touch;
|
|
scrollbar-width: none;
|
|
}
|
|
.snap-container::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
.snap-section {
|
|
height: 100dvh;
|
|
width: 100%;
|
|
scroll-snap-align: start;
|
|
scroll-snap-stop: always;
|
|
position: relative;
|
|
overflow: hidden;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
/* Utility to ensure content fits without vertical overflow */
|
|
.content-safe-area {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
align-items: center;
|
|
padding: 2rem 1rem;
|
|
width: 100%;
|
|
max-width: 1280px;
|
|
margin: 0 auto;
|
|
}
|
|
/* Floating heart animation */
|
|
@keyframes floatUp {
|
|
0% { transform: translateY(0) scale(0.5) translateX(0); opacity: 1; }
|
|
100% { transform: translateY(-160px) scale(1.6) translateX(var(--tx, 20px)); opacity: 0; }
|
|
}
|
|
.floating-heart {
|
|
position: absolute;
|
|
pointer-events: none;
|
|
animation: floatUp 2s ease-out forwards;
|
|
color: #ff4d4d;
|
|
font-size: 24px;
|
|
z-index: 50;
|
|
}
|
|
/* Custom scrollbar styling */
|
|
.custom-scrollbar {
|
|
overflow-y: auto;
|
|
scrollbar-width: thin;
|
|
scrollbar-color: rgba(166, 255, 234, 0.3) transparent;
|
|
}
|
|
.custom-scrollbar::-webkit-scrollbar {
|
|
width: 6px;
|
|
}
|
|
.custom-scrollbar::-webkit-scrollbar-track {
|
|
background: transparent;
|
|
}
|
|
.custom-scrollbar::-webkit-scrollbar-thumb {
|
|
background-color: rgba(166, 255, 234, 0.3);
|
|
border-radius: 3px;
|
|
}
|
|
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
|
|
background-color: rgba(166, 255, 234, 0.5);
|
|
}
|
|
/* No scrollbar utility */
|
|
.no-scrollbar {
|
|
scrollbar-width: none;
|
|
-ms-overflow-style: none;
|
|
}
|
|
.no-scrollbar::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
/* Slide in animation - 오른쪽에서 왼쪽으로 */
|
|
@keyframes slideInFromRight {
|
|
0% {
|
|
opacity: 0;
|
|
transform: translateX(100px);
|
|
max-width: 0;
|
|
}
|
|
50% {
|
|
max-width: 500px;
|
|
}
|
|
100% {
|
|
opacity: 1;
|
|
transform: translateX(0);
|
|
max-width: 600px;
|
|
}
|
|
}
|
|
.animate-slide-in {
|
|
animation: slideInFromRight 0.7s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
|
|
}
|
|
</style>
|
|
<script type="importmap">
|
|
{
|
|
"imports": {
|
|
"react/": "https://esm.sh/react@^19.2.3/",
|
|
"react": "https://esm.sh/react@^19.2.3",
|
|
"react-dom/": "https://esm.sh/react-dom@^19.2.3/"
|
|
}
|
|
}
|
|
</script>
|
|
</head>
|
|
<body class="bg-[#121a1d]">
|
|
<!-- Meta Pixel noscript fallback (head의 noscript에는 img가 허용되지 않아 body에 위치) -->
|
|
<noscript><img height="1" width="1" style="display:none"
|
|
src="https://www.facebook.com/tr?id=1572679738203392&ev=PageView&noscript=1"
|
|
/></noscript>
|
|
<div id="root"></div>
|
|
<script type="module" src="/src/index.tsx"></script>
|
|
</body>
|
|
</html>
|