diff --git a/src/css/common.css b/src/css/common.css index f0cf784..681b26a 100644 --- a/src/css/common.css +++ b/src/css/common.css @@ -872,11 +872,8 @@ body{overflow-x:hidden;} IBEPAGE — common.css 추가분 ════════════════════════════════ */ .ibe-channel-section { padding: 60px 0; } - .ibe-channel__title { font-size: 2rem; font-weight: 800; color: #1a1f3a; line-height: 1.35; letter-spacing: -0.02em; margin: 12px 0 16px; } - .ibe-channel__desc { font-size: 0.9rem; color: #666; line-height: 1.9; margin-bottom: 56px; } - .ibe-channel__diagram { position: relative; width: min(1540px, 100%); height: 430px; margin: 0 auto; display: grid; grid-template-columns: 420px 1fr 420px; align-items: center; } .ibe-channel__svg { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0; pointer-events: none; } @@ -892,22 +889,16 @@ body{overflow-x:hidden;} .ibe-channel__card span { font-size: 1rem; font-weight: 700; color: #1a1f3a; } .ibe-channel__center { position: relative; z-index: 3; display: flex; justify-content: center; align-items: center; } - .ibe-channel__center-img { width: 310px; object-fit: contain; filter: drop-shadow(0 24px 35px rgba(93,47,151,0.22)); } .ibe-channel__svg path { fill: none; stroke: rgba(139,92,246,0.35); stroke-width: 2; stroke-dasharray: 12 6; animation: ibe-flow 2s linear infinite; } - .ibe-channel__svg path { fill: none; stroke: rgba(139,92,246,0.35); stroke-width: 2; stroke-dasharray: 12 6; animation: ibe-flow 2s linear infinite; } - - .ibe-channel__svg path:nth-child(1), .ibe-channel__svg path:nth-child(2), .ibe-channel__svg path:nth-child(3) { animation-name: ibe-flow-right; } - .ibe-channel__svg path:nth-child(4), .ibe-channel__svg path:nth-child(5), .ibe-channel__svg path:nth-child(6) { animation-name: ibe-flow-left; } - .ibe-channel__svg path:nth-child(2) { animation-delay: 0.3s; } .ibe-channel__svg path:nth-child(3) { animation-delay: 0.6s; } .ibe-channel__svg path:nth-child(5) { animation-delay: 0.3s; } @@ -933,4 +924,35 @@ body{overflow-x:hidden;} .ibe-channel__card span { font-size: 0.85rem; } } @keyframes ibe-flow-right { from { stroke-dashoffset: 0; } to { stroke-dashoffset: -36; } } -@keyframes ibe-flow-left { from { stroke-dashoffset: 0; } to { stroke-dashoffset: 36; } } \ No newline at end of file +@keyframes ibe-flow-left { from { stroke-dashoffset: 0; } to { stroke-dashoffset: 36; } } + + +.ibe-booking-section { padding: 60px 0 80px; border-top: 1px solid #f0f0f0; } +.ibe-booking__title { font-size: 2rem; font-weight: 800; color: #1a1f3a; margin: 12px 0 56px; letter-spacing: -0.02em; } +.ibe-booking__flow { display: flex; align-items: flex-start; justify-content: center; } +.ibe-booking__item { display: flex; flex-direction: column; align-items: center; flex: 1; } +.ibe-booking__connector { flex: 1; position: relative; height: 4px; margin-top: 40px; } +.ibe-booking__line-bg { position: absolute; top: 50%; left: 0; right: 0; height: 1px; background: rgba(139,92,246,0.15); } +.ibe-booking__line-flow { position: absolute; top: 50%; left: 0; right: 0; height: 2px; overflow: hidden; } +.ibe-booking__line-flow::after { content: ''; position: absolute; top: 0; left: -40%; width: 40%; height: 100%; background: linear-gradient(90deg, transparent, rgba(139,92,246,0.8), transparent); animation: ibe-booking-flow 1.8s linear infinite; animation-delay: var(--delay, 0s); } +.ibe-booking__icon { font-size: 32px; background: linear-gradient(135deg, #a78bfa, #ec4899); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } + +@keyframes ibe-booking-flow { from { left: -40%; } to { left: 100%; } } +.ibe-booking__circle { width: 88px; height: 88px; border-radius: 50%; background: #f4f5fb; display: flex; align-items: center; justify-content: center; box-shadow: 5px 5px 12px rgba(0,0,0,0.08), -5px -5px 12px #fff; margin-bottom: 20px; } +.ibe-booking__circle img { width: 48px; height: 48px; object-fit: contain; } +.ibe-booking__num { font-size: 10px; font-weight: 700; color: var(--color-primary-light); letter-spacing: 0.1em; margin-bottom: 6px; } +.ibe-booking__label { font-size: 14px; font-weight: 700; color: var(--color-primary); margin-bottom: 8px; } +.ibe-booking__desc { font-size: 12px; color: #888; line-height: 1.7; text-align: center; } + +@media (max-width: 768px) { + .ibe-booking__flow { flex-direction: column; align-items: flex-start; gap: 24px; } + .ibe-booking__item { flex-direction: row; align-items: center; gap: 16px; text-align: left; } + .ibe-booking__circle { flex-shrink: 0; width: 64px; height: 64px; margin-bottom: 0; } + .ibe-booking__circle img { width: 36px; height: 36px; } + .ibe-booking__connector { width: 2px; height: 32px; margin: 0 0 0 32px; } + .ibe-booking__line-bg { top: 0; bottom: 0; left: 50%; width: 1px; height: 100%; } + .ibe-booking__line-flow { top: 0; left: 50%; width: 2px; height: 100%; } + .ibe-booking__line-flow::after { width: 100%; height: 40%; left: 0; top: -40%; background: linear-gradient(180deg, transparent, rgba(139,92,246,0.8), transparent); animation: ibe-booking-flow-v 1.8s linear infinite; animation-delay: var(--delay, 0s); } + @keyframes ibe-booking-flow-v { from { top: -40%; } to { top: 100%; } } + .ibe-booking__desc { text-align: left; } +} \ No newline at end of file diff --git a/src/pages/solution/IbePage.jsx b/src/pages/solution/IbePage.jsx index c664359..15517c0 100644 --- a/src/pages/solution/IbePage.jsx +++ b/src/pages/solution/IbePage.jsx @@ -1,10 +1,46 @@ import useFadeIn from "../../hooks/useFadeIn"; import SubHero from "../../components/SubHero"; -import { useRef } from "react"; +import { useRef, useState } from "react"; import { motion, useInView, AnimatePresence } from "framer-motion"; - +import { + Search, + Armchair, + CalendarClock, + Wallet, + Ticket, + ArrowUpRight, +} from "lucide-react"; const ease = [0.22, 1, 0.36, 1]; +const FUNCTIONS = [ + { num: "01", img: "./images/s1-01.jpg", label: "비행가능 지역 및 공역표출" }, + { num: "02", img: "./images/s1-02.jpg", label: "비행체 위치 표출" }, + { + num: "03", + img: "./images/s1-03.jpg", + label: "항공기 비행경로 및 히스토리 표출", + }, + { num: "04", img: "./images/s1-04.jpg", label: "항공기 비행정보 표출" }, + { num: "05", img: "./images/s1-05.jpg", label: "비행계획서 조회" }, + { num: "06", img: "./images/s1-06.jpg", label: "비정상 상황의 경보 표출" }, +]; + +const FLOW = [ + { + step: "01", + label: "비행체 식별", + desc: "항공기·드론·선박 실시간 신호 수집", + }, + { + step: "02", + label: "데이터 수집", + desc: "위치·속도·고도·식별코드 통합 처리", + }, + { step: "03", label: "관제 서버", desc: "통합 관제 서버 분석 및 상황 판단" }, + { step: "04", label: "모니터링", desc: "관제사 화면 실시간 현황 표출" }, + { step: "05", label: "경보·대응", desc: "이상 상황 감지 즉시 경보 및 대응" }, +]; + function IbePage() { const basePath = import.meta.env.BASE_URL; @@ -13,12 +49,22 @@ function IbePage() { const introInView = useInView(introRef, { once: true, margin: "-60px" }); const channelRef = useRef(null); const channelInView = useInView(channelRef, { once: true, margin: "-60px" }); + const bookingRef = useRef(null); + const bookingInView = useInView(bookingRef, { once: true, margin: "-60px" }); + const funcRef = useRef(null); + const funcInView = useInView(funcRef, { once: true, margin: "-80px" }); + const flowRef = useRef(null); + const flowInView = useInView(flowRef, { once: true, margin: "-60px" }); + const SOLUTION_NAV = [ { label: "비행상황관리 시스템", to: "/solution/flight-control" }, { label: "IBE", to: "/solution/ibe" }, // { label: "스마트 관광 예약 플랫폼", to: "/solution/smart-tour" }, // { label: "KT G-cloud 인천총판", to: "/solution/kt-gcloud" }, ]; + + const [activeIdx, setActiveIdx] = useState(0); + return (
+ {/* BOOKING PROCESS */} +
+ + Booking Process + + + 직관적이고 간편한 예약 프로세스 + + +
+ {[ + { + num: "01", + icon: Search, + label: "검색", + desc: "출발지, 도착지, 일정,\n탑승객 정보를 입력하여\n최적의 항공편 검색", + }, + { + num: "02", + icon: Armchair, + label: "선택", + desc: "운임, 스케줄, 좌석 등\n다양한 옵션을 비교하고\n원하는 항공편 선택", + }, + { + num: "03", + icon: CalendarClock, + label: "예약", + desc: "승객 정보 입력 및\n부가 서비스 선택을 통해\n예약을 진행", + }, + { + num: "04", + icon: Wallet, + label: "결제", + desc: "다양한 결제 수단을 지원하여\n안전하고 간편하게\n결제 진행", + }, + { + num: "05", + icon: Ticket, + label: "발권", + desc: "E-ticket 발행 및\n예약 확인을 통해\n예약 완료", + }, + ].map((item, i) => { + const Icon = item.icon; + return ( + <> + +
+ + + + + + + + + +
+ {item.num} + {item.label} +

+ {item.desc.split("\n").map((line, j) => ( + + {line} +
+
+ ))} +

+
+ {i < 4 && ( +
+
+
+
+ )} + + ); + })} +
+
{/* MULTI CHANNEL INTEGRATION */}
+ + {/* 4. 주요기능 */} +
+ + 주요기능 + +
+
    + {FUNCTIONS.map(({ num, label }, i) => ( + setActiveIdx(i)} + initial={{ opacity: 0, y: 16 }} + animate={funcInView ? { opacity: 1, y: 0 } : {}} + transition={{ duration: 0.5, ease, delay: 0.05 * i }} + > + {num} + {label} + + + + + + ))} +
+
+ + + {FUNCTIONS[activeIdx].label} +
+ + {FUNCTIONS[activeIdx].num} + + + {FUNCTIONS[activeIdx].label} + +
+
+
+
+
+
+ + {/* 5. 시스템 구성 흐름 */} +
+ + 시스템 구성 + +
+ {FLOW.map(({ step, label, desc }, i) => ( + + {step} + {label} +

{desc}

+ {i < FLOW.length - 1 && ( + + )} + + ))} +
+