2025-12-17 12:59:26 +09:00
< ? php require_once 'session.php' ; ?>
<! DOCTYPE html >
< html lang = " ko " >
< head >
< meta charset = " UTF-8 " >
< meta name = " viewport " content = " width=device-width, initial-scale=1.0 " >
< title > CodeBridge - X SAM - 영업관리 </ title >
< script src = " https://cdn.tailwindcss.com " ></ script >
< script src = " https://unpkg.com/lucide@latest " ></ script >
< link href = " https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Noto+Sans+KR:wght@300;400;500;600;700&display=swap " rel = " stylesheet " >
< script >
tailwind . config = {
theme : {
extend : {
fontFamily : {
sans : [ 'Inter' , 'Noto Sans KR' , 'sans-serif' ],
},
colors : {
brand : {
50 : '#f0f9ff' ,
100 : '#e0f2fe' ,
200 : '#bae6fd' ,
500 : '#0ea5e9' ,
600 : '#0284c7' ,
700 : '#0369a1' ,
900 : '#0c4a6e' ,
}
},
animation : {
blob : " blob 7s infinite " ,
'fade-in-up' : 'fadeInUp 0.8s ease-out forwards' ,
},
keyframes : {
blob : {
" 0% " : { transform : " translate(0px, 0px) scale(1) " },
" 33% " : { transform : " translate(30px, -50px) scale(1.1) " },
" 66% " : { transform : " translate(-20px, 20px) scale(0.9) " },
" 100% " : { transform : " translate(0px, 0px) scale(1) " },
},
fadeInUp : {
'0%' : { opacity : '0' , transform : 'translateY(20px)' },
'100%' : { opacity : '1' , transform : 'translateY(0)' },
}
},
}
}
}
</ script >
< style >
. delay - 100 { animation - delay : 100 ms ; }
. delay - 200 { animation - delay : 200 ms ; }
. delay - 300 { animation - delay : 300 ms ; }
. animation - delay - 2000 { animation - delay : 2 s ; }
. animation - delay - 4000 { animation - delay : 4 s ; }
/* Hide scrollbar for clean modal */
. no - scroll { overflow : hidden ; }
</ style >
</ head >
< body class = " bg-slate-50 text-slate-900 font-sans selection:bg-brand-200 selection:text-brand-900 " >
<!-- Toast Notification -->
< div id = " toast " class = " fixed top-24 right-4 z-[60] bg-slate-800 text-white px-6 py-4 rounded-xl shadow-2xl flex items-center gap-3 transition-all duration-500 transform translate-x-full opacity-0 " >
< i data - lucide = " check-circle-2 " class = " text-green-400 w-6 h-6 " ></ i >
< div >
< h4 class = " font-bold text-sm " > 다운로드 시작됨 </ h4 >
< p class = " text-slate-400 text-xs " > CodeBridgeX_Proposal_v2 . 4. pdf </ p >
</ div >
</ div >
<!-- Navigation -->
< nav class = " sticky top-0 z-30 bg-white/80 backdrop-blur-md border-b border-slate-200 " >
< div class = " max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 " >
< div class = " flex justify-between items-center h-16 " >
< div class = " flex items-center gap-3 cursor-pointer " onclick = " filterAssets('All') " >
< div class = " w-8 h-8 bg-brand-600 rounded-lg flex items-center justify-center text-white font-bold text-lg shadow-lg shadow-brand-200 " >
S
</ div >
< span class = " text-xl font-bold tracking-tight text-slate-900 " > CodeBridgeX < span class = " text-brand-600 " > SAM </ span ></ span >
</ div >
< div class = " flex items-center gap-4 " >
< a href = " sales_scenario/ " class = " text-sm font-medium text-slate-600 hover:text-brand-600 transition-colors " > 영업 시나리오 </ a >
< a href = " sales_manager_scenario/ " class = " text-sm font-medium text-slate-600 hover:text-brand-600 transition-colors " > 매니저 시나리오 </ a >
< a href = " salesmanagement/ " class = " text-sm font-medium text-slate-600 hover:text-brand-600 transition-colors " > 영업관리 </ a >
2025-12-17 15:41:30 +09:00
< a href = " corp/kodata.php " class = " text-sm font-medium text-slate-600 hover:text-brand-600 transition-colors " > 기업분석 </ a >
2025-12-17 12:59:26 +09:00
< ? php if ( isset ( $_SESSION [ 'userid' ]) && $_SESSION [ 'userid' ] != '' ) : ?>
< div class = " hidden sm:flex items-center gap-2 ml-2 " >
< div class = " w-8 h-8 rounded-full bg-slate-200 flex items-center justify-center text-slate-500 font-bold border border-slate-300 " >
< ? = mb_substr ( $_SESSION [ 'name' ], 0 , 1 ) ?>
</ div >
< span class = " text-sm font-medium text-slate-700 " >< ? = $_SESSION [ 'name' ] ?> 님</span>
< a href = " login/logout.php " class = " px-3 py-1.5 bg-slate-100 text-slate-600 text-xs font-bold rounded hover:bg-slate-200 transition-colors border border-slate-200 " > 로그아웃 </ a >
</ div >
< ? php else : ?>
< a href = " login/login_form.php " class = " px-4 py-2 bg-brand-600 text-white text-sm font-bold rounded-lg hover:bg-brand-700 transition-colors shadow-lg shadow-brand-200 " >
로그인
</ a >
< ? php endif ; ?>
</ div >
</ div >
</ div >
</ nav >
<!-- Hero Section -->
< header class = " relative bg-white pt-16 pb-20 lg:pt-24 lg:pb-28 overflow-hidden " >
< div class = " max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative z-10 " >
< div class = " text-center max-w-4xl mx-auto " >
< div class = " inline-flex items-center gap-2 px-3 py-1 rounded-full bg-brand-50 text-brand-700 text-xs font-semibold uppercase tracking-wider mb-6 animate-fade-in-up " >
< i data - lucide = " shield-check " class = " w-4 h-4 " ></ i >
CEO Management Solution
</ div >
< h1 class = " text-4xl sm:text-5xl lg:text-6xl font-extrabold text-slate-900 tracking-tight mb-6 animate-fade-in-up delay-100 " >
2025-12-17 13:49:47 +09:00
직원 관리 도구가 아닙니다 .< br />
2025-12-17 12:59:26 +09:00
< span class = " text-transparent bg-clip-text bg-gradient-to-r from-brand-600 to-indigo-600 " >
대표님 경영 무기입니다 .
</ span >
</ h1 >
< p class = " text-lg sm:text-xl text-slate-500 mb-10 leading-relaxed max-w-2xl mx-auto animate-fade-in-up delay-200 " >
" SAM " 은 단순한 ERP가 아닙니다 . < br class = " hidden sm:block " />
가지급금 이자 계산부터 실시간 경영 알림까지 .< br />
< strong > 오직 CEO를 위한 시크릿 대시보드 </ strong > 를 제안하십시오 .
</ p >
< div class = " flex justify-center gap-4 animate-fade-in-up delay-300 relative z-20 " >
< button onclick = " showDownloadToast() " class = " px-8 py-3 rounded-xl bg-slate-900 text-white font-semibold hover:bg-slate-800 hover:shadow-lg transition-all transform hover:-translate-y-1 active:scale-95 " >
제안서 다운로드
</ button >
< button onclick = " filterAssets('Demo') " class = " px-8 py-3 rounded-xl bg-white text-slate-700 border border-slate-200 font-semibold hover:bg-slate-50 hover:border-slate-300 transition-all flex items-center gap-2 active:scale-95 " >
< i data - lucide = " layout-grid " class = " w-5 h-5 " ></ i >
세일즈 덱 보기
</ button >
</ div >
<!-- Main Hero Image -->
< div class = " mt-16 relative z-10 animate-fade-in-up delay-300 " >
< div class = " relative rounded-2xl overflow-hidden shadow-2xl border-4 border-white/50 bg-white " >
< img src = " img/sam_project.jpg " alt = " SAM Project Dashboard " class = " w-full h-auto object-cover " >
< div class = " absolute inset-0 bg-gradient-to-t from-slate-900/10 to-transparent pointer-events-none " ></ div >
</ div >
<!-- Decorative Elements around image -->
< div class = " absolute -top-10 -right-10 w-24 h-24 bg-brand-400 rounded-full mix-blend-multiply filter blur-2xl opacity-40 animate-blob " ></ div >
< div class = " absolute -bottom-10 -left-10 w-24 h-24 bg-indigo-400 rounded-full mix-blend-multiply filter blur-2xl opacity-40 animate-blob animation-delay-2000 " ></ div >
</ div >
</ div >
</ div >
<!-- Background Decorations -->
< div class = " absolute top-0 left-1/2 -translate-x-1/2 w-full h-full z-0 pointer-events-none " >
< div class = " absolute top-20 left-10 w-72 h-72 bg-brand-200 rounded-full mix-blend-multiply filter blur-3xl opacity-30 animate-blob " ></ div >
< div class = " absolute top-20 right-10 w-72 h-72 bg-indigo-200 rounded-full mix-blend-multiply filter blur-3xl opacity-30 animate-blob animation-delay-2000 " ></ div >
< div class = " absolute -bottom-8 left-1/2 w-72 h-72 bg-pink-200 rounded-full mix-blend-multiply filter blur-3xl opacity-30 animate-blob animation-delay-4000 " ></ div >
</ div >
</ header >
<!-- Main Content -->
< main class = " max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12 " >
< div class = " flex flex-col sm:flex-row items-center justify-between mb-8 gap-4 " >
< h2 class = " text-2xl font-bold text-slate-900 " > 영업 자료 </ h2 >
< div id = " filter-buttons " class = " flex flex-wrap gap-2 justify-center " >
<!-- Filter buttons injected by JS -->
</ div >
</ div >
<!-- Grid Container -->
< div id = " assets-grid " class = " grid grid-cols-1 md:grid-cols-3 gap-6 auto-rows-auto " >
<!-- Cards injected by JS -->
</ div >
< div id = " empty-state " class = " hidden text-center py-20 text-slate-400 col-span-3 " >
해당 카테고리에 자료가 없습니다 .
</ div >
</ main >
<!-- Footer -->
< footer class = " bg-white border-t border-slate-200 py-12 mt-12 " >
< div class = " max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex flex-col md:flex-row justify-between items-center gap-6 " >
< p class = " text-slate-500 text-sm " > © 2025 CodeBridge - X Corp . 영업 관리 </ p >
< div class = " flex gap-6 " >
< a href = " # " class = " text-slate-400 hover:text-slate-600 " > 사내 전용 ( 대외비 ) </ a >
< a href = " # " class = " text-slate-400 hover:text-slate-600 " > 영업 스크립트 </ a >
< a href = " # " class = " text-slate-400 hover:text-slate-600 " > 고객 지원 </ a >
</ div >
</ div >
</ footer >
<!-- Modal Backdrop & Modal -->
< div id = " modal-backdrop " class = " fixed inset-0 bg-slate-900/50 backdrop-blur-sm z-50 hidden transition-opacity opacity-0 " onclick = " closeModal() " ></ div >
< div id = " modal-container " class = " fixed inset-0 z-50 flex items-center justify-center p-4 pointer-events-none hidden " >
<!-- Modal Content injected by JS -->
</ div >
< script >
// Data - Ported from constants.ts
const ASSETS = [
{
id : '1' , type : 'TEXT' , title : 'Concept: 대표를 위한 무기' ,
content : '기존 ERP는 직원의 관리 도구였지만, SAM은 대표님의 의사결정 무기입니다. 직원의 보고를 기다리지 마십시오. SAM이 대표님께 직접, 실시간으로 회사의 현황을 보고합니다.' ,
script : " 대표님, ERP나 MES 들어보셨죠? 보통 직원들이 입력하고 관리하는 도구입니다. 정작 대표님은 직원한테 보고를 받아야만 회사를 알 수 있죠. SAM은 반대입니다. 직원이 아니라 '대표님을 위한 무기'입니다. 외근 중이든 집이든, 대표님 폰에서 회사의 자금, 인력, 리스크가 한눈에 보입니다. " ,
tags : [ 'Concept' , 'Pitch' , 'Opener' ], gridSpan : 'col-span-1' , rowSpan : 'row-span-1'
},
{
id : '3' , type : 'VIDEO' , title : 'CEO 시크릿 대시보드' , src : 'https://images.unsplash.com/photo-1551288049-bebda4e38f71?ixlib=rb-4.0.3&auto=format&fit=crop&w=2670&q=80' , videoTitle : 'CEO Dashboard Demo' ,
embedHtml : '<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/1146972515?title=0&byline=0&portrait=0&badge=0&autopause=0&player_id=0&app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share" referrerpolicy="strict-origin-when-cross-origin" style="position:absolute;top:0;left:0;width:100%;height:100%;" title="CEO의_경영_비서,_SAM"></iframe></div>' ,
description : '가지급금 이자 4.6%, 예상 부가세, 자금 현황이 오직 대표님 화면에만 실시간으로 계산되어 표시됩니다.' ,
script : " 이 화면은 직원들은 못 봅니다. 오직 대표님 아이디로 로그인했을 때만 뜹니다. 여기 붉은 글씨 보이시죠? 현재 가지급금에 대한 인정이자 4.6%가 실시간으로 계산돼서 '대표님, 세금 폭탄 조심하세요'라고 경고해주는 겁니다. 세무사가 알려주기 전에 SAM이 먼저 알려드립니다. " ,
tags : [ 'Demo' , 'Dashboard' , 'Finance' ], gridSpan : 'col-span-1 md:col-span-2' , rowSpan : 'row-span-2'
},
{
id : '4' , type : 'TEXT' , title : '20가지 고충 해결' ,
content : '사람(근태, 인수인계), 돈(세금, 자금), 운영(현장관리), 대표의 삶(리스크). CEO가 겪는 20가지 핵심 고충을 시스템 하나로 방어합니다.' ,
script : " 중소기업 대표님의 머릿속을 20가지로 정리해봤습니다. 직원 근태, 자금 압박, 세무 조사... 이 모든 걸 혼자 감당하고 계시지 않습니까? SAM은 단순 프로그램이 아니라, 이 20가지 리스크를 막아주는 방패입니다. " ,
tags : [ 'Pain Points' , 'Solution' ], gridSpan : 'col-span-1' , rowSpan : 'row-span-1'
},
{
id : '5' , type : 'IMAGE' , title : '모바일 & 감성 알림' , src : 'img/sam_alert.jpg' ,
description : '수주/입금 시 울리는 "SAM~" 알림음. 외근 중에도 회사가 돌아가는 소리를 들으세요.' ,
script : " 가장 인기 있는 기능입니다. 외근 나가 계실 때 불안하시죠? 직원이 큰 수주를 따오거나, 거래처에서 돈을 입금하면 대표님 폰에서 'SAM~' 하고 알림이 옵니다. 그 소리만 들으면 '아, 우리 회사 잘 돌아가고 있구나' 안심이 되실 겁니다. " ,
tags : [ 'Mobile' , 'UX' , 'Emotion' ], gridSpan : 'col-span-1 md:col-span-2' , rowSpan : 'row-span-1'
},
{
id : '6' , type : 'VIDEO' , title : '영업 전략 해부: CEO에게 파는 법' ,
src : 'https://images.unsplash.com/photo-1552664730-d307ca884978?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80' ,
embedHtml : '<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/1146961422?title=0&byline=0&portrait=0&badge=0&autopause=0&player_id=0&app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share" referrerpolicy="strict-origin-when-cross-origin" style="position:absolute;top:0;left:0;width:100%;height:100%;" title="영업_전략_해부__CEO에게_파는_법"></iframe></div>' ,
content : 'SAM 프로젝트의 핵심 영업 전략은 CEO들의 **심리적 약점과 욕구(통제 욕구, 복잡한 것 회피, 비용 민감성)**를 파고들어 설득력을 극대화하도록 재정비되었습니다.' ,
script : " 1. 통제 욕구 및 불안감 자극/해소: 지각/무단결근 등 특이사항과 내일 나갈 돈(예상 부가세)을 미리 보여주어 통제감을 높여줍니다. \n 2. 복잡한 것 회피: 모바일 중심의 '시크릿 모드'와 10초 사용을 강조하여 진입장벽을 낮춥니다. \n 3. 비용 민감성: 월 30~50만 원으로 24시간 AI 경영 비서를 고용하는 가성비를 강조합니다. " ,
tags : [ 'Strategy' , 'CEO Psychology' , 'Sales Pitch' ], gridSpan : 'col-span-1 md:col-span-2' , rowSpan : 'row-span-1'
},
{
id : '7' , type : 'IMAGE' , title : '자동화 & 인수인계' , src : 'img/sam_time.jpg' ,
description : '직원이 갑자기 퇴사해도 걱정 없습니다. 견적부터 발주, 출고까지 모든 이력이 클릭 한 번으로 자동 인수인계됩니다.' ,
script : " 직원이 갑자기 그만둔다고 하면 눈앞이 캄캄하시죠? 파일 어디 있냐, 거래처 연락처 뭐냐... SAM을 쓰시면 그럴 일 없습니다. 모든 업무 기록이 서버에 남기 때문에, 후임자는 '클릭' 한 번이면 전임자의 모든 업무를 그대로 이어받습니다. " ,
tags : [ 'Automation' , 'Management' ], gridSpan : 'col-span-1' , rowSpan : 'row-span-2' , customAspect : 'aspect-[3/5]'
},
{
id : '9' , type : 'TEXT' , title : '도입 제안 (Closing)' ,
content : '월 구독료로 수천만 원대 맞춤형 ERP 기능과 개인 비서를 고용하는 효과를 누리십시오. 내일부터는 "걱정" 대신 "설렘"으로 출근하십시오.' ,
script : " 직원 한 명 월급의 1/10도 안 되는 비용입니다. 이 돈으로 24시간 비서, 그리고 완벽한 경영 시스템을 고용하시는 겁니다. 오늘 결정하시고, 내일부터는 가벼운 마음으로 출근하십시오. " ,
tags : [ 'Closing' , 'Pricing' ], gridSpan : 'col-span-1' , rowSpan : 'row-span-1'
},
{
id : '10' , type : 'AUDIO' , title : '[Core Features] 대표님이 반할 기능 8선' , src : 'm4a/strategy.m4a' ,
content : 'AI 경영 비서부터 자금/세무 관리까지, SAM이 제공하는 8가지 핵심 기능을 3분 요약으로 들어보세요.' ,
script : " AI 경영 비서: 음성 인식 업무일지, 회의록, 자동 번역 \n 스마트 현장: 사진 토큰 관리, GPS 기반 출퇴근, QR 설비 관리 \n 자금/세무: 예상 부가세, 법인카드 한도 관리, 경리일보 자동화 \n 리스크 방어: 미수금 알림, 재고 부족 경고, 신규 거래처 신용 등급 표시 \n 편의 기능: 용량 걱정 없는 무제한 파일함, 시그니처 매출 알림음 " ,
tags : [ 'Podcast' , 'Audio' , 'Feature' ], gridSpan : 'col-span-1 md:col-span-2' , rowSpan : 'row-span-1'
},
{
id : '11' , type : 'TEXT' , title : '1. 대표님의 고민 (Pain Points)' ,
content : '매출은 느는데 이익은 제자리? 직원과 현장을 100% 믿을 수 있나? 세금 낼 때마다 자금 계획이 꼬이나? 이는 정보 부재에서 오는 "전략적 리스크"입니다.' ,
script : " 매출은 계속 오르는데, 왜 통장에 남는 돈은 없을까요? 직원들은 정말 열심히 하고 있는 걸까요? 세금 낼 때마다 목돈 마련하느라 허덕이시진 않나요? 더 많은 보고서가 아니라, 대표님 손안에 '진짜 정보'가 필요할 때입니다. " ,
tags : [ 'Pain Points' , 'Risk' , 'Needs' ], gridSpan : 'col-span-1' , rowSpan : 'row-span-1'
},
{
id : '12' , type : 'TEXT' , title : '2. 새로운 해법 (Solution)' ,
content : 'SAM은 "실무자 관리 도구"가 아닌 "CEO 의사결정 도구"입니다. 복잡한 입력은 AI가, 대표님은 직관적인 신호등과 요약 카드만 확인하십시오.' ,
script : " 기존 ERP는 관리자용이라 복잡하고 비쌉니다. SAM은 다릅니다. 오직 대표님을 위해 설계되었습니다. 복잡한 표 대신 신호등으로, PC 대신 모바일로, 수천만 원 구축비 대신 합리적 구독료로 제공합니다. 복잡한 건 AI에게 맡기고, 대표님은 흐름만 보십시오. " ,
tags : [ 'Solution' , 'Differentiation' , 'AI' ], gridSpan : 'col-span-1' , rowSpan : 'row-span-1'
},
{
id : '13' , type : 'TEXT' , title : '3. 핵심 기능 (Core Features)' ,
content : '리스크 사전 방지(미수금, 재고), 자금 흐름 관리(예상 부가세, 한도 체크), 실시간 현장 통제(지각, AI 업무일지).' ,
script : " A업체 미수금 3개월 경과, 접대비 한도 80% 소진, 오늘 지각자 3명... 대표님이 놓치기 쉬운 '리스크'만 골라서 붉은색 알림을 띄워드립니다. 사무실 밖에서도 현장과 자금이 한눈에 들어옵니다. " ,
tags : [ 'Features' , 'Risk' , 'Finance' , 'Ops' ], gridSpan : 'col-span-1 md:col-span-1' , rowSpan : 'row-span-1'
},
{
id : '14' , type : 'STAT' , title : '4. 도입 효과 (ROI)' , statValue : '0분' , statLabel : '업무 보고 시간' ,
content : '보고 시간 0분(실시간 확인), 단순 업무 80% 자동화, 의사결정 속도 즉시. 눈에 보이는 비용 절감과 경쟁력 강화를 경험하십시오.' ,
script : " 직원이 보고서 만들어서 결재 올릴 때까지 기다리지 마십시오. SAM을 쓰면 보고 시간이 '0분'이 됩니다. 단순 반복 업무는 80% 자동화됩니다. 이게 바로 돈 버는 시스템입니다. " ,
tags : [ 'ROI' , 'Efficiency' , 'Automation' ], gridSpan : 'col-span-1' , rowSpan : 'row-span-1'
},
{
id : '15' , type : 'STAT' , title : '5. 제안 (Investment)' , statValue : '1/100' , statLabel : '채용 대비 비용' ,
content : '연 3,000만 원 경리 직원 채용 vs 월 30만 원 AI 비서. 24시간 잠들지 않는 AI를 신입사원 월급의 1/10도 안 되는 비용으로 고용하십시오.' ,
script : " 사람 한 명 뽑으려면 3천만 원 듭니다. SAM은 월 30만 원입니다. 1/100 비용으로 24시간 잠들지 않고 실수도 없는 완벽한 AI 비서를 채용하시는 겁니다. 이건 지출이 아니라 가장 확실한 투자입니다. " ,
tags : [ 'Investment' , 'Cost' , 'Value' ], gridSpan : 'col-span-1' , rowSpan : 'row-span-1'
},
{
id : '16' , type : 'TEXT' , title : '6. 다음 단계 (Next Steps)' ,
content : '백 번 설명보다 한 번의 경험이 낫습니다. 대표님 업종에 맞춘 "무료 진단 & 시연"과 "3일 무료 체험"을 신청하십시오.' ,
script : " 우리 회사에 맞을까 고민하지 마세요. 대표님 업종에 딱 맞춘 대시보드를 미리 구성해서 보여드립니다. 3일만 직접 써보시면, 왜 SAM이 필수인지 바로 아실 겁니다. " ,
tags : [ 'Call to Action' , 'Demo' , 'Free Trial' ], gridSpan : 'col-span-1' , rowSpan : 'row-span-1'
}
];
// Constants
const FILTERS = [ '전체' , 'CEO 설득' , '데모' ];
let activeFilter = '전체' ;
// DOM Elements
const gridEl = document . getElementById ( 'assets-grid' );
const filterContainer = document . getElementById ( 'filter-buttons' );
const emptyState = document . getElementById ( 'empty-state' );
const modalBackdrop = document . getElementById ( 'modal-backdrop' );
const modalContainer = document . getElementById ( 'modal-container' );
const toast = document . getElementById ( 'toast' );
// Initial Render
function init () {
renderFilters ();
renderGrid ();
lucide . createIcons ();
}
// Filter Logic
function renderFilters () {
filterContainer . innerHTML = FILTERS . map ( filter => `
< button
onclick = " filterAssets(' ${ filter } ') "
class = " px-4 py-2 rounded-lg text-sm font-medium transition-colors duration-200 $ { activeFilter === filter ? 'bg-slate-900 text-white shadow-md' : 'bg-white text-slate-600 hover:bg-slate-100 border border-transparent hover:border-slate-200'} "
>
$ { filter }
</ button >
` ) . join ( '' );
}
window . filterAssets = ( filter ) => {
activeFilter = filter ;
renderFilters ();
renderGrid ();
lucide . createIcons ();
};
function getFilteredAssets () {
if ( activeFilter === '전체' ) return ASSETS ;
return ASSETS . filter ( asset => {
if ( activeFilter === 'CEO 설득' ) return asset . tags . some ( tag => [ 'Concept' , 'Pitch' , 'Pain Points' , 'Solution' , 'Closing' ] . includes ( tag ));
if ( activeFilter === '데모' ) return asset . tags . some ( tag => [ 'Demo' , 'Dashboard' , 'Video' , 'Mobile' , 'UX' , 'Infra' ] . includes ( tag ));
return true ;
});
}
// Grid Render
function renderGrid () {
const assets = getFilteredAssets ();
if ( assets . length === 0 ) {
emptyState . classList . remove ( 'hidden' );
} else {
emptyState . classList . add ( 'hidden' );
}
gridEl . innerHTML = assets . map ( asset => {
let contentRaw = '' ;
let iconName = '' ;
let badgeColor = '' ;
// Determine card content based on type
if ( asset . type === 'TEXT' ) {
contentRaw = `<p class="text-slate-600 mb-4 leading-relaxed line-clamp-3">${asset.content}</p>` ;
iconName = 'file-text' ;
badgeColor = 'bg-blue-100 text-blue-700' ;
} else if ( asset . type === 'STAT' ) {
contentRaw = `
< div class = " flex items-end gap-2 mb-2 " >
< span class = " text-4xl font-bold text-slate-900 tracking-tight " > $ { asset . statValue } </ span >
< span class = " text-sm font-medium text-slate-500 mb-1.5 " > $ { asset . statLabel } </ span >
</ div >
< p class = " text-slate-600 text-sm line-clamp-2 " > $ { asset . script . substring ( 0 , 100 )} ...</ p >
` ;
iconName = 'bar-chart-2' ;
badgeColor = 'bg-emerald-100 text-emerald-700' ;
} else if ( asset . type === 'IMAGE' || asset . type === 'VIDEO' ) {
const aspectClass = asset . customAspect || 'aspect-video' ;
contentRaw = `
< div class = " mb-4 rounded-lg overflow-hidden border border-slate-100 relative group ${ aspectClass } " >
< img src = " ${ asset.src } " alt = " ${ asset.title } " class = " w-full h-full object-cover transform group-hover:scale-105 transition-transform duration-500 " >
$ { asset . type === 'VIDEO' ? `
< div class = " absolute inset-0 bg-black/40 flex items-center justify-center group-hover:bg-black/30 transition-all " >
< div class = " w-12 h-12 rounded-full bg-white/90 flex items-center justify-center pl-1 shadow-lg transform group-hover:scale-110 transition-transform " >
< i data - lucide = " play " class = " w-5 h-5 text-slate-900 fill-slate-900 " ></ i >
</ div >
</ div >
` : '' }
</ div >
< p class = " text-slate-600 text-sm line-clamp-2 " > $ { asset . description || asset . script } </ p >
` ;
iconName = asset . type === 'VIDEO' ? 'video' : 'image' ;
badgeColor = asset . type === 'VIDEO' ? 'bg-violet-100 text-violet-700' : 'bg-pink-100 text-pink-700' ;
} else if ( asset . type === 'AUDIO' ) {
contentRaw = `
< div class = " mb-4 rounded-xl overflow-hidden bg-slate-900 p-6 relative group flex items-center justify-between gap-4 " >
< div class = " flex items-center gap-4 z-10 " >
< div class = " w-12 h-12 rounded-full bg-indigo-500 flex items-center justify-center text-white shrink-0 animate-pulse " >
< i data - lucide = " headphones " class = " w-6 h-6 " ></ i >
</ div >
< div >
< div class = " text-white font-bold text-sm mb-1 " > SAM Podcast </ div >
< div class = " text-slate-400 text-xs " > 3 : 42 • Strategy Brief </ div >
</ div >
</ div >
< div class = " w-8 h-8 rounded-full bg-white/10 flex items-center justify-center text-white group-hover:bg-white/20 transition-colors z-10 " >
< i data - lucide = " play " class = " w-4 h-4 fill-white " ></ i >
</ div >
<!-- Waveform effect -->
< div class = " absolute inset-0 opacity-20 flex items-end justify-between px-4 pb-2 gap-1 pointer-events-none " >
< div class = " w-1 h-3 bg-white rounded-full " ></ div >< div class = " w-1 h-5 bg-white rounded-full " ></ div >< div class = " w-1 h-8 bg-white rounded-full " ></ div >< div class = " w-1 h-4 bg-white rounded-full " ></ div >
< div class = " w-1 h-6 bg-white rounded-full " ></ div >< div class = " w-1 h-2 bg-white rounded-full " ></ div >< div class = " w-1 h-5 bg-white rounded-full " ></ div >< div class = " w-1 h-7 bg-white rounded-full " ></ div >
< div class = " w-1 h-3 bg-white rounded-full " ></ div >< div class = " w-1 h-6 bg-white rounded-full " ></ div >< div class = " w-1 h-4 bg-white rounded-full " ></ div >< div class = " w-1 h-2 bg-white rounded-full " ></ div >
</ div >
</ div >
< p class = " text-slate-600 text-sm line-clamp-2 " > $ { asset . content } </ p >
` ;
iconName = 'mic' ;
badgeColor = 'bg-indigo-100 text-indigo-700' ;
}
return `
< div class = " bg-white rounded-2xl border border-slate-100 p-6 hover:shadow-xl transition-all duration-300 hover:-translate-y-1 cursor-pointer group h-full flex flex-col ${ asset.gridSpan } ${ asset.rowSpan } " onclick = " openModal(' ${ asset.id } ') " >
< div class = " flex justify-between items-start mb-4 " >
< div class = " flex items-center gap-2 " >
< span class = " inline-flex items-center gap-1 px-2.5 py-0.5 rounded-full text-xs font-semibold ${ badgeColor } " >
< i data - lucide = " ${ iconName } " class = " w-3 h-3 " ></ i >
$ { asset . type }
</ span >
$ { asset . tags [ 0 ] ? `<span class="text-xs text-slate-400 font-medium">#${asset.tags[0]}</span>` : '' }
</ div >
< button class = " text-slate-400 hover:text-brand-600 transition-colors " >
< i data - lucide = " arrow-up-right " class = " w-4 h-4 " ></ i >
</ button >
</ div >
< h3 class = " text-xl font-bold text-slate-900 mb-3 group-hover:text-brand-600 transition-colors " > $ { asset . title } </ h3 >
< div class = " flex-grow " >
$ { contentRaw }
</ div >
< div class = " mt-6 pt-4 border-t border-slate-50 flex items-center justify-between text-xs font-medium text-slate-400 opacity-0 group-hover:opacity-100 transition-opacity duration-300 " >
< span > 클릭하여 상세 보기 </ span >
< span > 핵심 스크립트 & 자료 </ span >
</ div >
</ div >
` ;
}) . join ( '' );
}
// Modal Logic
window . openModal = ( id ) => {
const asset = ASSETS . find ( a => a . id === id );
if ( ! asset ) return ;
// Generate content
const tagsHtml = asset . tags . map ( tag => `<span class="px-2 py-1 rounded-md bg-slate-100 text-slate-500 text-xs font-medium">#${tag}</span>` ) . join ( '' );
let mediaHtml = '' ;
if ( asset . src ) {
if ( asset . type === 'VIDEO' ) {
mediaHtml = `
< div class = " aspect-video bg-slate-100 rounded-xl overflow-hidden mb-6 relative group " >
< img src = " ${ asset.src } " class = " w-full h-full object-cover " >
< div class = " absolute inset-0 bg-black/40 flex items-center justify-center " >
< div class = " w-16 h-16 rounded-full bg-white/90 flex items-center justify-center pl-1 shadow-lg " >
< i data - lucide = " play " class = " w-6 h-6 text-slate-900 fill-slate-900 " ></ i >
</ div >
</ div >
</ div > ` ;
// Override with embed HTML if present (for Vimeo)
if ( asset . embedHtml ) {
mediaHtml = `<div class="aspect-video bg-slate-100 rounded-xl overflow-hidden mb-6 relative z-0">${asset.embedHtml}</div>` ;
}
} else if ( asset . type === 'AUDIO' ) {
mediaHtml = `
< div class = " bg-slate-900 rounded-xl p-8 mb-6 text-center " >
< div class = " w-24 h-24 rounded-full bg-indigo-500 mx-auto mb-6 flex items-center justify-center shadow-lg hover:scale-105 transition-transform " >
< i data - lucide = " mic " class = " w-10 h-10 text-white " ></ i >
</ div >
< h4 class = " text-white font-bold text-xl mb-2 " > $ { asset . title } </ h4 >
< p class = " text-slate-400 text-sm mb-6 " > SAM Strategy Podcast • 3 : 42 </ p >
< audio controls class = " w-full " >
< source src = " ${ asset.src } " type = " audio/mp4 " >
< source src = " ${ asset.src } " type = " audio/mpeg " >
Your browser does not support the audio element .
</ audio >
</ div >
` ;
} else {
const aspectClass = asset . customAspect || 'aspect-video' ;
const objectFitClass = asset . customAspect ? 'object-contain p-2' : 'object-cover' ;
mediaHtml = `<div class="${aspectClass} bg-slate-100 rounded-xl overflow-hidden mb-6"><img src="${asset.src}" class="w-full h-full ${objectFitClass}"></div>` ;
}
}
const modalContent = `
< div class = " bg-white rounded-2xl shadow-2xl w-full max-w-2xl max-h-[90vh] overflow-y-auto pointer-events-auto scale-95 opacity-0 transition-all duration-300 " id = " modal-card " >
< div class = " sticky top-0 bg-white/90 backdrop-blur-sm p-4 border-b border-slate-100 flex justify-between items-center z-10 " >
< div class = " flex items-center gap-2 " >
< h3 class = " text-lg font-bold text-slate-900 " > $ { asset . title } </ h3 >
< span class = " px-2 py-0.5 rounded-full text-xs font-bold bg-slate-900 text-white " > $ { asset . type } </ span >
</ div >
< button onclick = " closeModal() " class = " w-8 h-8 rounded-full bg-slate-50 hover:bg-slate-100 flex items-center justify-center text-slate-500 transition-colors " >
< i data - lucide = " x " class = " w-5 h-5 " ></ i >
</ button >
</ div >
< div class = " p-6 sm:p-8 " >
$ { mediaHtml }
$ { asset . content ? `<div class="mb-8 p-4 bg-slate-50 rounded-xl border border-slate-100 text-slate-700 leading-relaxed font-medium">${asset.content}</div>` : '' }
< div class = " mb-8 " >
< div class = " flex items-center gap-2 mb-3 " >
< div class = " w-1 h-5 rounded-full bg-brand-500 " ></ div >
< h4 class = " font-bold text-slate-900 " > Sales Script </ h4 >
</ div >
< div class = " bg-indigo-50/50 p-5 rounded-xl border border-indigo-100 relative " >
< i data - lucide = " quote " class = " w-5 h-5 text-indigo-200 absolute top-4 left-4 " ></ i >
< p class = " text-slate-800 leading-relaxed pl-6 relative z-10 font-medium " > " ${ asset.script } " </ p >
</ div >
</ div >
$ { asset . statValue ? `
< div class = " grid grid-cols-2 gap-4 mb-8 " >
< div class = " p-4 rounded-xl bg-white border border-slate-200 text-center " >
< div class = " text-xs text-slate-400 uppercase tracking-wider font-semibold mb-1 " > 핵심 가치 </ div >
< div class = " text-2xl font-bold text-slate-900 " > $ { asset . statValue } </ div >
</ div >
< div class = " p-4 rounded-xl bg-white border border-slate-200 text-center " >
< div class = " text-xs text-slate-400 uppercase tracking-wider font-semibold mb-1 " > 카테고리 </ div >
< div class = " text-2xl font-bold text-slate-900 " > $ { asset . statLabel } </ div >
</ div >
</ div >
` : '' }
< div class = " flex flex-wrap gap-2 pt-6 border-t border-slate-100 " >
$ { tagsHtml }
</ div >
</ div >
< div class = " p-4 border-t border-slate-100 bg-slate-50 rounded-b-2xl flex justify-end gap-3 " >
< button onclick = " closeModal() " class = " px-4 py-2 rounded-lg bg-white border border-slate-200 text-slate-700 font-medium hover:bg-slate-50 transition-colors " > 닫기 </ button >
< button onclick = " showDownloadToast(); closeModal() " class = " px-4 py-2 rounded-lg bg-brand-600 text-white font-medium hover:bg-brand-700 shadow-md transition-colors flex items-center gap-2 " >
< i data - lucide = " download " class = " w-4 h-4 " ></ i >
자료 사용하기
</ button >
</ div >
</ div >
` ;
modalContainer . innerHTML = modalContent ;
// Animation In
modalBackdrop . classList . remove ( 'hidden' );
modalContainer . classList . remove ( 'hidden' );
document . body . classList . add ( 'no-scroll' );
// Trigger reflow
void modalBackdrop . offsetWidth ;
modalBackdrop . classList . remove ( 'opacity-0' );
const card = document . getElementById ( 'modal-card' );
card . classList . remove ( 'scale-95' , 'opacity-0' );
lucide . createIcons ();
};
window . closeModal = () => {
const card = document . getElementById ( 'modal-card' );
if ( card ) {
card . classList . add ( 'scale-95' , 'opacity-0' );
}
modalBackdrop . classList . add ( 'opacity-0' );
setTimeout (() => {
modalBackdrop . classList . add ( 'hidden' );
modalContainer . classList . add ( 'hidden' );
document . body . classList . remove ( 'no-scroll' );
modalContainer . innerHTML = '' ;
}, 300 );
};
// Toast
window . showDownloadToast = () => {
toast . classList . remove ( 'translate-x-full' , 'opacity-0' );
setTimeout (() => {
toast . classList . add ( 'translate-x-full' , 'opacity-0' );
}, 3000 );
};
// Initialize
init ();
</ script >
< script src = " https://player.vimeo.com/api/player.js " ></ script >
</ body >
</ html >