Browse Source

feat : 솔루션 ui 변경

remotes/origin/main
이시연 2 weeks ago
parent
commit
011cfcede7
  1. 358
      src/components/main/MainSolution.jsx
  2. 215
      src/css/main.css

358
src/components/main/MainSolution.jsx

@ -1,26 +1,14 @@
import { useEffect, useRef, useState } from "react";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { Plane, Radio, Ship, Car } from "lucide-react";
import { Link } from "react-router-dom";
gsap.registerPlugin(ScrollTrigger);
const BARS = [
{ label: "월", h: 45 },
{ label: "화", h: 60 },
{ label: "수", h: 50 },
{ label: "목", h: 75 },
{ label: "금", h: 65 },
{ label: "토", h: 85 },
{ label: "일", h: 100, active: true },
];
gsap.registerPlugin(ScrollTrigger);
function FlightMockup({ animate }) {
const cnt1Ref = useRef(null);
const cnt2Ref = useRef(null);
const cnt3Ref = useRef(null);
const row1Ref = useRef(null);
const row2Ref = useRef(null);
const barsRef = useRef([]);
const statsRef = useRef([]);
const rowsRef = useRef([]);
useEffect(() => {
if (!animate) return;
@ -30,185 +18,227 @@ function FlightMockup({ animate }) {
const step = target / (duration / 16);
const t = setInterval(() => {
start = Math.min(start + step, target);
el.textContent = Math.round(start);
el.textContent = Math.round(start).toLocaleString();
if (start >= target) clearInterval(t);
}, 16);
return t;
}
const timers = [];
timers.push(countUp(statsRef.current[0], 1325, 1000));
timers.push(countUp(statsRef.current[1], 642, 800));
timers.push(countUp(statsRef.current[2], 386, 900));
timers.push(countUp(statsRef.current[3], 216, 700));
timers.push(countUp(statsRef.current[4], 81, 600));
//
timers.push(countUp(cnt1Ref.current, 24, 800));
timers.push(countUp(cnt2Ref.current, 138, 1000));
timers.push(countUp(cnt3Ref.current, 7, 600));
// row
[row1Ref.current, row2Ref.current].forEach((r, i) => {
const t = setTimeout(() => {
r.style.opacity = "1";
r.style.transform = "translateY(0)";
}, i * 200);
timers.push(t);
});
//
barsRef.current.forEach((b, i) => {
rowsRef.current.forEach((r, i) => {
const t = setTimeout(
() => {
if (b) b.style.transform = "scaleY(1)";
if (r) {
r.style.opacity = "1";
r.style.transform = "translateY(0)";
}
},
400 + i * 80,
300 + i * 150,
);
timers.push(t);
});
return () => timers.forEach(clearTimeout);
return () =>
timers.forEach((t) => {
clearTimeout(t);
clearInterval(t);
});
}, [animate]);
const stats = [
{ label: "전체", sub: "+12 실시간", icon: null },
{
label: "항공기",
sub: "운항 중",
icon: <Plane size={14} color="#a78bfa" />,
},
{
label: "무인기",
sub: "운항 중",
icon: <Radio size={14} color="#60a5fa" />,
},
{ label: "선박", sub: "항해 중", icon: <Ship size={14} color="#34d399" /> },
{ label: "차량", sub: "이동 중", icon: <Car size={14} color="#fb923c" /> },
];
return (
<div className="mock-win">
<div className="mock-win__bar">
<span className="mock-dot mock-dot--red" />
<span className="mock-dot mock-dot--yellow" />
<span className="mock-dot mock-dot--green" />
<span className="mock-win__title">실시간 운항 현황</span>
<span className="mock-win__badge">운항 24</span>
</div>
<div className="mock-stat-chips">
<div className="mock-chip">
<div className="mock-chip__val" ref={cnt1Ref}>
0
</div>
<div className="mock-chip__label">운항 </div>
</div>
<div className="mock-chip">
<div className="mock-chip__val" ref={cnt2Ref}>
0
</div>
<div className="mock-chip__label">완료</div>
</div>
<div className="mock-chip">
<div className="mock-chip__val" ref={cnt3Ref}>
0
</div>
<div className="mock-chip__label">대기</div>
<div className="dark-closeup">
<div className="dark-top-bar">
<div className="dark-top-bar__title">
<span className="dark-top-bar__live" />
실시간 이동체 현황
</div>
<div className="dark-top-bar__time">2025.06.10 14:32:07</div>
</div>
<div className="dark-stat-grid">
{stats.map((s, i) => (
<div
className="mock-flight-row mock-flight-row--active mock-flight-row--anim"
ref={row1Ref}
key={i}
className={`dark-stat-card${i === 0 ? " dark-stat-card--total" : ""}`}
>
<div>
<div className="mock-flight-row__route">ICN LAX</div>
<div className="mock-flight-row__info">
KE-201 · 08:30 출발 · 이코노미
</div>
</div>
<div className="mock-flight-row__right">
<div className="mock-flight-row__alt">11,000m</div>
<div className="mock-flight-row__altlabel">현재 고도</div>
</div>
</div>
<div className="mock-flight-row mock-flight-row--anim" ref={row2Ref}>
<div>
<div className="mock-flight-row__route">GMP CJU</div>
<div className="mock-flight-row__info">OZ-104 · 09:15 출발</div>
</div>
<div className="mock-flight-row__right">
<div className="mock-flight-row__alt">6,500m</div>
<div className="mock-flight-row__altlabel">현재 고도</div>
</div>
</div>
<div className="mock-chart">
<div className="mock-chart__head">
<span>일별 운항 편수</span>
<span>최근 7</span>
</div>
<div className="mock-chart__bars">
{BARS.map((b, i) => (
<div key={b.label} className="mock-chart__bar-wrap">
<div className="dark-stat-card__label">{s.label}</div>
<div
className={`mock-chart__bar mock-chart__bar--anim${b.active ? " mock-chart__bar--active" : ""}`}
style={{ height: `${b.h}%` }}
className="dark-stat-card__val"
ref={(el) => {
barsRef.current[i] = el;
statsRef.current[i] = el;
}}
/>
<div
className={`mock-chart__bar-label${b.active ? " mock-chart__bar-label--active" : ""}`}
>
{b.label}
0
</div>
<div className="dark-stat-card__sub">{s.sub}</div>
</div>
))}
</div>
<div className="dark-table-head">
<span>구분</span>
<span>사용/현황</span>
<span>상태</span>
<span>속도</span>
<span>고도</span>
</div>
{[
{
id: "✈ 항공기",
name: "KAI 123",
status: "운항 중",
statusType: "green",
speed: "820km/h",
alt: "10,200m",
},
{
id: "⬡ 무인기",
name: "DRN-045",
status: "운항 중",
statusType: "green",
speed: "45km/h",
alt: "120m",
},
{
id: "⚓ 선박",
name: "SEA-001",
status: "대기",
statusType: "yellow",
speed: "–",
alt: "–",
},
].map((row, i) => (
<div
key={i}
className={`dark-table-row dark-table-row--anim${i === 0 ? " dark-table-row--active" : ""}`}
ref={(el) => {
rowsRef.current[i] = el;
}}
>
<span className="dark-cell dark-cell--id">{row.id}</span>
<span className="dark-cell">{row.name}</span>
<span>
<span className={`dark-badge dark-badge--${row.statusType}`}>
{row.status}
</span>
</span>
<span className="dark-cell">{row.speed}</span>
<span className="dark-cell">{row.alt}</span>
</div>
))}
</div>
);
}
function BookingMockup({ animate }) {
function IBEMockup({ animate }) {
const priceRef = useRef(null);
useEffect(() => {
if (!animate) return;
let val = 0;
const target = 892000;
const step = target / 40;
const t = setInterval(() => {
val = Math.min(val + step, target);
val = Math.min(val + 3000, 120000);
if (priceRef.current)
priceRef.current.textContent = "₩" + Math.round(val).toLocaleString();
if (val >= target) clearInterval(t);
priceRef.current.textContent = val.toLocaleString() + " KRW";
if (val >= 120000) clearInterval(t);
}, 20);
return () => clearInterval(t);
}, [animate]);
return (
<div className="mock-win">
<div className="mock-win__bar">
<span className="mock-dot mock-dot--red" />
<span className="mock-dot mock-dot--yellow" />
<span className="mock-dot mock-dot--green" />
<span className="mock-win__title">결제 정보 확인</span>
<span className="mock-win__badge mock-win__badge--blue">
3 / 3 단계
</span>
</div>
<div className="mock-ticket">
<div className="light-closeup">
<div className="light-header">
<div className="light-header__logo"> PAL Networks</div>
<div className="light-header__nav">
<span className="active">검색</span>
<span>선택</span>
<span>일정추가</span>
<span>부가서비스</span>
<span>결제</span>
<span>발권</span>
</div>
</div>
<div className="light-search-box">
<div className="light-search-city">
<div className="light-search-city__label">출발지</div>
<div className="light-search-city__val">SEL</div>
<div className="light-search-city__sub">서울 (ICN)</div>
</div>
<div className="light-search-arrow"></div>
<div className="light-search-city">
<div className="light-search-city__label">도착지</div>
<div className="light-search-city__val">NRT</div>
<div className="light-search-city__sub">도쿄 (NRT)</div>
</div>
<div className="light-search-city">
<div className="light-search-date__label">출발일</div>
<div className="light-search-date__val">2024.06.15 ()</div>
</div>
<div className="light-search-btn">검색</div>
</div>
<div className="light-result-label">
<span>128개의</span> 일정 검색됨
</div>
{[
{ dep: "09:00", arr: "11:20", price: null, active: true },
{ dep: "12:30", arr: "14:50", price: "150,000 KRW", active: false },
{ dep: "18:20", arr: "20:40", price: "120,000 KRW", active: false },
].map((f, i) => (
<div
key={i}
className={`light-flight${f.active ? " light-flight--active" : ""}`}
>
<div className="light-flight__times">
<div>
<div className="mock-ticket__route">ICN LAX</div>
<div className="mock-ticket__info">
KE-201 · 2025.08.14 · 성인 1
</div>
</div>
<div className="mock-ticket__price" ref={priceRef}>
0
<div className="light-flight__time">{f.dep}</div>
<div className="light-flight__info">ICN</div>
</div>
<div>
<div className="light-flight__arrow"></div>
<div className="light-flight__stop">2시간 20</div>
</div>
<div className="mock-card-wrap">
<div className="mock-card-inner">
<div className="mock-card-front">
<div className="mock-card-chip" />
<div className="mock-card-num">4521 3847</div>
<div className="mock-card-bottom">
<div className="mock-card-name">KIM CHULSOO</div>
<div className="mock-card-exp">08/27</div>
<div>
<div className="light-flight__time">{f.arr}</div>
<div className="light-flight__info">NRT</div>
</div>
</div>
<div className="light-flight__right">
<div
className="light-flight__price"
ref={f.active ? priceRef : null}
>
{f.active ? "0 KRW" : f.price}
</div>
<div className="light-flight__btn">선택</div>
</div>
<div className="mock-price-row">
<span className="mock-price-label">최종 결제금액</span>
<span className="mock-price-val"> 892,000</span>
</div>
<div className="mock-pay-btn">결제하기</div>
))}
</div>
);
}
function MainSolution() {
const sectionRef = useRef(null);
const headRef = useRef(null);
@ -217,18 +247,21 @@ function MainSolution() {
const solutions = [
{
label: "SOLUTION 01",
title: "비행상황관리 시스템",
desc: "운항 상태, 항로, 고도, 비행 이력을 실시간으로 확인하고 관리합니다.",
label: "비행 관리",
title: "비행상황관리\n시스템",
desc: "항공기, 무인기, 선박, 차량 등 다양한 이동체의 실시간 위치와 운항 상태를 하나의 플랫폼에서 통합 모니터링합니다. 고도, 속도, 항로 이력을 정밀하게 추적하고, 이상 상황 발생 시 즉각적인 대응이 가능합니다.",
mockup: "flight",
link: "/solution/flight-control",
theme: "dark",
},
{
label: "SOLUTION 02",
label: "예약 시스템",
title: "IBE",
desc: "항공 예약과 판매 흐름을 연결해 편리한 예약 환경을 제공합니다.",
mockup: "booking",
titleSub: "Internet Booking Engine",
desc: "항공권 검색부터 예약, 결제, 발권까지 모든 프로세스를 하나로 연결하는 차세대 예약 엔진입니다. 다양한 채널과 시스템을 유연하게 연동하여 최적의 예약 경험을 제공합니다.",
mockup: "ibe",
link: "/solution/ibe",
theme: "light",
},
];
@ -241,12 +274,8 @@ function MainSolution() {
.timeline({
scrollTrigger: {
trigger: sectionRef.current,
start: "top 72%",
end: "top 28%",
scrub: 1,
once: true,
start: "top 70%",
onEnter: () => setAnimate(true),
onLeaveBack: () => setAnimate(false),
},
})
.to(headRef.current, {
@ -274,7 +303,6 @@ function MainSolution() {
return (
<section className="main-solution-section" ref={sectionRef}>
<div className="main-solution-bg-circle" />
<div className="main-solution-inner">
<div className="main-solution-head" ref={headRef}>
<p className="main-solution-eyebrow">PAL SOLUTION</p>
@ -293,32 +321,36 @@ function MainSolution() {
{solutions.map((item, index) => (
<article
key={index}
className="main-solution-card"
className={`main-solution-card main-solution-card--${item.theme}`}
ref={(el) => {
cardsRef.current[index] = el;
}}
>
<div className="main-solution-card-top">
<span className="main-solution-card-label">{item.label}</span>
<div className="main-solution-card-left">
<div>
<span className="main-solution-card-tag">{item.label}</span>
<h3 className="main-solution-card-title">
{item.title}
{item.title.split("\n").map((line, i) => (
<span key={i}>
{line}
{i === 0 && <br />}
</span>
))}
</h3>
{item.titleSub && (
<small className="main-solution-card-title-sub">
<p className="main-solution-card-title-sub">
{item.titleSub}
</small>
</p>
)}
</h3>
<p className="main-solution-card-desc">{item.desc}</p>
</div>
<Link to={item.link} className="main-solution-card-link">
자세히 보기{" "}
<span className="main-solution-card-link__arrow"></span>
자세히 보기 <span></span>
</Link>
</div>
<div className="main-solution-card-mockup">
<div className="main-solution-card-right">
{item.mockup === "flight" && <FlightMockup animate={animate} />}
{item.mockup === "booking" && (
<BookingMockup animate={animate} />
)}
{item.mockup === "ibe" && <IBEMockup animate={animate} />}
</div>
</article>
))}

215
src/css/main.css

@ -282,121 +282,130 @@ body{overflow-x:hidden;}
@keyframes UTMShine{0%,48%{transform:translateX(-120%);opacity:0;}58%{opacity:.75;}76%,100%{transform:translateX(120%);opacity:0;}}
@keyframes float-UTM{0%{transform:translateY(0px);}48%{transform:translateY(-1px);}100%{transform:translateY(0px);}}
/* solution */
.main-solution-section { position: relative; height: auto; min-height: 100dvh; overflow: visible; padding: 120px 8vw 160px; background: linear-gradient(180deg,#ffffff 0%,#f7f9ff 52%,#ffffff 100%); }
.main-solution-section::before{content:"";position:absolute;inset:0;background:radial-gradient(circle at 8% 10%,rgba(26,31,94,.045),transparent 30%),radial-gradient(circle at 86% 76%,rgba(112,180,255,.08),transparent 34%);pointer-events:none;}
.main-solution-inner { position: relative; z-index: 2; max-width: 1660px; margin: 0 auto; }
.main-solution-arrow{width:42px;height:42px;margin:0 auto 46px;display:flex;align-items:center;justify-content:center;font-size:34px;line-height:1;color:#1a1f5e;opacity:.82;}
.main-solution-head{max-width:760px;margin-bottom:54px;will-change:transform,opacity;}
.main-solution-eyebrow { margin: 0 0 16px; font-size: 12px; font-weight: 800; letter-spacing: .24em; color: #9333ea; opacity: 0.75; }
.main-solution-head { max-width: 760px; margin-bottom: 54px; }
.main-solution-eyebrow { margin: 0 0 16px; font-size: 12px; font-weight: 800; letter-spacing: .24em; color: #8b5cf6; opacity: 0.75; }
.main-solution-title { margin: 0; font-size: clamp(42px,5vw,76px); font-weight: 800; line-height: 1.02; letter-spacing: -.07em; color: #10142b; }
.main-solution-desc{margin:24px 0 0;max-width:620px;font-size:17px;line-height:1.8;font-weight:500;color:rgba(16,20,43,.62);word-break:keep-all;}
.main-solution-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; }
.main-solution-card { border-radius: 24px; background: #fff; border: 1px solid rgba(26,31,94,0.08); overflow: hidden; display: flex; flex-direction: column; box-shadow: 0 8px 40px rgba(26,31,94,0.07); }
.main-solution-card-top { padding: 28px 28px 20px; min-height: 180px; display: flex; flex-direction: column; }
.main-solution-card-link { display: inline-flex; align-items: center; gap: 6px; margin-top: auto; padding-top: 16px; font-size: 13px; font-weight: 700; color: #1a1f5e; text-decoration: none; transition: gap 0.2s ease; }
.main-solution-card-link:hover { gap: 10px; }
.main-solution-card-link__arrow { font-size: 14px; transition: transform 0.2s ease; }
.main-solution-card-link:hover .main-solution-card-link__arrow { transform: translateX(3px); }
.main-solution-card-label { display: block; font-size: 11px; font-weight: 700; letter-spacing: .18em; color: #6366F1; margin-bottom: 8px; }
.main-solution-card-title { font-size: 22px; font-weight: 800; color: #10142b; letter-spacing: -.04em; margin: 0 0 10px; line-height: 1.2; }
.main-solution-card-title-sub { display: block; font-size: 13px; font-weight: 500; color: rgba(16,20,43,.42); letter-spacing: 0; margin-top: 4px; }
.main-solution-card-desc { font-size: 14px; color: rgba(16,20,43,.55); line-height: 1.75; margin: 0; }
.main-solution-card-mockup { background: #f4f6fc; border-top: 1px solid rgba(26,31,94,0.07); flex: 1; overflow: hidden; position: relative; min-height: 380px; padding: 20px 20px 0; display: flex; align-items: flex-start; justify-content: center; }
.main-solution-card-mockup::after { content: ""; position: absolute; bottom: 0; left: 0; right: 0; height: 80px; background: linear-gradient(to bottom, transparent, #f4f6fc); pointer-events: none; }
/* mock 공통 */
.mock-win { background: #fff; border: 1px solid rgba(26,31,94,0.09); border-radius: 12px 12px 0 0; width: 100%; overflow: hidden; box-shadow: 0 4px 24px rgba(26,31,94,0.08); }
.mock-win__bar { display: flex; align-items: center; gap: 5px; padding: 9px 14px; border-bottom: 1px solid rgba(26,31,94,0.07); }
.mock-win__title { font-size: 11px; color: rgba(16,20,43,.4); margin-left: 8px; flex: 1; }
.mock-win__badge { font-size: 10px; padding: 2px 8px; border-radius: 20px; background: rgba(139,92,246,0.07); color: #6d28d9; font-weight: 600; }
.mock-win__badge--blue { background: rgba(99,102,241,0.07); color: #4338ca; }
.mock-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; }
.mock-dot--red { background: #ef4444; }
.mock-dot--yellow { background: #eab308; }
.mock-dot--green { background: #22c55e; }
/* stats */
.mock-stat-chips { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; padding: 12px; }
.mock-chip { background: #f4f6fc; border-radius: 8px; padding: 10px 12px; text-align: center; }
.mock-chip__val { font-size: 18px; font-weight: 700; color: #10142b; }
.mock-chip__label { font-size: 10px; color: rgba(16,20,43,.4); margin-top: 3px; }
/* flight rows */
.mock-flight-row { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; border-top: 1px solid rgba(26,31,94,0.06); }
.mock-flight-row--active { background: rgba(139,92,246,0.04); border-left: 3px solid rgba(139,92,246,0.5); }
.mock-flight-row__route { font-size: 14px; font-weight: 700; color: #10142b; margin-bottom: 3px; }
.mock-flight-row__info { font-size: 10px; color: rgba(16,20,43,.4); }
.mock-flight-row__right { text-align: right; }
.mock-flight-row__alt { font-size: 16px; font-weight: 700; color: #10142b; }
.mock-flight-row__altlabel { font-size: 10px; color: rgba(16,20,43,.38); margin-top: 2px; }
.mock-flight-row--anim { opacity: 0; transform: translateY(8px); transition: opacity 0.4s ease, transform 0.4s ease; }
/* 차트 */
.mock-chart { padding: 14px 16px 0; border-top: 1px solid rgba(26,31,94,0.06); }
.mock-chart__head { display: flex; justify-content: space-between; font-size: 10px; color: rgba(16,20,43,.4); margin-bottom: 10px; }
.mock-chart__bars { display: flex; align-items: flex-end; gap: 5px; height: 64px; }
.mock-chart__bar-wrap { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 4px; height: 100%; justify-content: flex-end; }
.mock-chart__bar { width: 100%; border-radius: 3px 3px 0 0; background: #ede9fe; }
.mock-chart__bar--active { background: rgba(109,40,217,0.6); }
.mock-chart__bar-label { font-size: 9px; color: rgba(16,20,43,.35); }
.mock-chart__bar-label--active { color: rgba(109,40,217,0.7); font-weight: 600; }
.mock-chart__bar--anim { transform: scaleY(0); transform-origin: bottom; transition: transform 0.5s cubic-bezier(0.22, 1, 0.36, 1); }
/* booking */
.mock-ticket { margin: 14px 16px; background: #f4f6fc; border-radius: 10px; padding: 12px 14px; display: flex; align-items: center; justify-content: space-between; }
.mock-ticket__route { font-size: 14px; font-weight: 700; color: #10142b; }
.mock-ticket__info { font-size: 10px; color: rgba(16,20,43,.4); margin-top: 3px; }
.mock-ticket__price { font-size: 16px; font-weight: 700; color: #6d28d9; opacity: 0.85; }
.mock-card-wrap { margin: 0 16px 12px; perspective: 800px; }
.mock-card-inner { position: relative; height: 100px; transform-style: preserve-3d; transition: transform 0.7s cubic-bezier(0.22, 1, 0.36, 1); }
.mock-card-inner.flipped { transform: rotateY(180deg); }
.mock-card-front, .mock-card-back { position: absolute; inset: 0; border-radius: 10px; backface-visibility: hidden; padding: 14px 16px; display: flex; flex-direction: column; }
.mock-card-front { background: linear-gradient(135deg, #312e81 0%, #1e1b4b 100%); justify-content: space-between; }
.mock-card-back { background: linear-gradient(135deg, #1e1b4b 0%, #312e81 100%); transform: rotateY(180deg); align-items: center; justify-content: center; gap: 6px; }
.mock-card-cvv-label { font-size: 10px; color: rgba(255,255,255,0.5); }
.mock-card-cvv { font-size: 20px; font-weight: 700; color: #fff; letter-spacing: .2em; }
.mock-card-area { margin: 0 16px 12px; }
.mock-card-label { font-size: 10px; color: rgba(16,20,43,.4); margin-bottom: 6px; }
.mock-card-visual { background: linear-gradient(135deg, #312e81 0%, #1e1b4b 100%); border-radius: 10px; padding: 14px 16px; display: flex; flex-direction: column; gap: 10px; }
.mock-card-chip { width: 24px; height: 18px; background: #f0c040; border-radius: 3px; }
.mock-card-num { font-size: 13px; font-weight: 600; color: rgba(255,255,255,0.9); letter-spacing: .15em; }
.mock-card-bottom { display: flex; justify-content: space-between; }
.mock-card-name { font-size: 10px; color: rgba(255,255,255,0.6); }
.mock-card-exp { font-size: 10px; color: rgba(255,255,255,0.6); }
.mock-price-row { display: flex; justify-content: space-between; align-items: center; padding: 10px 16px; border-top: 1px solid rgba(26,31,94,0.07); }
.mock-price-label { font-size: 12px; font-weight: 600; color: #10142b; }
.mock-price-val { font-size: 15px; font-weight: 700; color: #6d28d9; opacity: 0.85; }
.mock-pay-btn { margin: 10px 16px 14px; background: linear-gradient(135deg, #1e1b4b 0%, #4c1d95 100%); border-radius: 8px; padding: 11px; text-align: center; font-size: 13px; font-weight: 700; color: #fff; }
.mock-flight-card--active { background: rgba(168,85,247,0.06); border-left: 3px solid #a855f7; }
.mock-flight-card__price { color: #7c3aed; }
.main-solution-desc { margin: 24px 0 0; max-width: 620px; font-size: 17px; line-height: 1.8; font-weight: 500; color: rgba(16,20,43,.62); word-break: keep-all; }
.main-solution-grid { display: flex; flex-direction: column; gap: 20px; }
.main-solution-card { border-radius: 24px; overflow: hidden; display: grid; grid-template-columns: 1fr 1.2fr; min-height: 320px; }
.main-solution-card--dark { background: #eef0ff; }
.main-solution-card--light { background: #f0f4ff; }
.main-solution-card-left { padding: 40px; display: flex; flex-direction: column; justify-content: space-between; }
.main-solution-card-tag { display: inline-block; background: #1a1f5e; color: #fff; font-size: 11px; font-weight: 700; padding: 5px 12px; border-radius: 999px; margin-bottom: 18px; }
.main-solution-card-title { font-size: 34px; font-weight: 800; color: #10142b; letter-spacing: -.04em; margin: 0 0 12px; line-height: 1.2; }
.main-solution-card-title-sub { font-size: 12px; color: rgba(16,20,43,.35); font-weight: 500; margin: 0 0 10px; }
.main-solution-card-desc { font-size: 13px; color: rgba(16,20,43,.52); line-height: 1.75; margin: 0; }
.main-solution-card-link { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 700; color: #10142b; background: #fff; padding: 9px 18px; border-radius: 999px; text-decoration: none; border: 1px solid rgba(26,31,94,0.1); transition: gap .2s; margin-top: 24px; width: fit-content; }
.main-solution-card-link:hover { gap: 12px; }
.main-solution-card-right { position: relative; overflow: hidden; display: flex; align-items: flex-end; justify-content: center; padding: 24px 24px 0; }
.main-solution-card--dark .main-solution-card-right::after { content: ""; position: absolute; bottom: 0; left: 0; right: 0; height: 60px; background: linear-gradient(to bottom, transparent, #eef0ff); pointer-events: none; z-index: 2; }
.main-solution-card--light .main-solution-card-right::after { content: ""; position: absolute; bottom: 0; left: 0; right: 0; height: 60px; background: linear-gradient(to bottom, transparent, #f0f4ff); pointer-events: none; z-index: 2; }
/* 다크 목업 */
.dark-closeup { width: 100%; background: #0d1117; border-radius: 12px 12px 0 0; overflow: hidden; box-shadow: 0 -8px 40px rgba(0,0,0,0.3); }
.dark-stat-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px; padding: 14px; }
.dark-stat-card { background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.07); border-radius: 10px; padding: 12px 14px; }
.dark-stat-card--total { border-color: rgba(255,255,255,0.12); background: rgba(255,255,255,0.07); }
.dark-stat-card__label { font-size: 9px; color: rgba(255,255,255,.55); letter-spacing: .06em; margin-bottom: 6px; font-weight: 600; }
.dark-stat-card__val { font-size: 22px; font-weight: 800; color: #fff; letter-spacing: -.03em; line-height: 1; margin-bottom: 4px; }
.dark-stat-card__sub { font-size: 9px; color: rgba(255,255,255,.4); }
.dark-top-bar__time { font-size: 10px; color: rgba(255,255,255,.2); }
.dark-top-bar { display: flex; align-items: center; justify-content: space-between; padding: 8px 14px; background: #161b22; border-bottom: 1px solid rgba(255,255,255,0.06); }
.dark-top-bar__title { font-size: 10px; color: rgba(255,255,255,.35); display: flex; align-items: center; gap: 6px; }
.dark-top-bar__live { display: inline-block; width: 6px; height: 6px; background: #e91e8c; border-radius: 50%; box-shadow: 0 0 6px rgba(233,30,140,0.8); }
.dark-top-bar__stats { display: flex; gap: 14px; }
.dark-top-bar__stat { font-size: 10px; color: rgba(255,255,255,.35); }
.dark-top-bar__stat span { color: #a78bfa; font-weight: 700; }
.dark-stat-card__icon { display: flex; align-items: center; margin-bottom: 8px; }
.dark-stat-card:nth-child(1) { border-color: rgba(255,255,255,0.1); background: rgba(255,255,255,0.05); }
.dark-stat-card:nth-child(2) { border-color: rgba(167,139,250,0.2); background: rgba(167,139,250,0.05); }
.dark-stat-card:nth-child(3) { border-color: rgba(96,165,250,0.2); background: rgba(96,165,250,0.05); }
.dark-stat-card:nth-child(4) { border-color: rgba(52,211,153,0.2); background: rgba(52,211,153,0.05); }
.dark-stat-card:nth-child(5) { border-color: rgba(251,146,60,0.2); background: rgba(251,146,60,0.05); }
.dark-table-head { display: grid; grid-template-columns: 0.9fr 0.9fr 0.8fr 0.7fr 0.6fr; padding: 6px 14px; background: rgba(255,255,255,0.03); font-size: 9px; color: rgba(255,255,255,.2); font-weight: 600; letter-spacing: .06em; border-top: 1px solid rgba(255,255,255,0.05); }
.dark-table-row { display: grid; grid-template-columns: 0.9fr 0.9fr 0.8fr 0.7fr 0.6fr; padding: 8px 14px; border-top: 1px solid rgba(255,255,255,0.04); align-items: center; }
.dark-table-row--active { background: rgba(139,92,246,0.1); border-left: 2px solid #7c3aed; }
.dark-table-row--anim { opacity: 0; transform: translateY(6px); transition: opacity 0.4s ease, transform 0.4s ease; }
.dark-cell { font-size: 10px; color: rgba(255,255,255,.65); }
.dark-cell--id { color: #a78bfa; font-weight: 700; }
.dark-badge { font-size: 9px; padding: 2px 6px; border-radius: 3px; font-weight: 600; display: inline-block; width: fit-content; }
.dark-badge--green { background: rgba(52,211,153,0.15); color: #34d399; }
.dark-badge--yellow { background: rgba(251,191,36,0.15); color: #fbbf24; }
.dark-table-row span { display: flex; align-items: center; }
/* 라이트 목업 (IBE) */
.light-closeup { width: 100%; background: #fff; border-radius: 12px 12px 0 0; overflow: hidden; box-shadow: 0 -8px 40px rgba(26,31,94,0.12); }
.light-header { display: flex; align-items: center; gap: 16px; padding: 10px 16px; border-bottom: 1px solid rgba(26,31,94,0.07); }
.light-header__logo { font-size: 12px; font-weight: 800; color: #1a1f5e; }
.light-header__nav { display: flex; gap: 12px; }
.light-header__nav span { font-size: 10px; color: rgba(16,20,43,.4); }
.light-header__nav span.active { color: #1a1f5e; font-weight: 600; border-bottom: 2px solid #1a1f5e; padding-bottom: 1px; }
.light-search-box { margin: 12px 14px; background: #f7f9ff; border: 1px solid rgba(26,31,94,0.1); border-radius: 12px; padding: 12px 14px; display: flex; align-items: center; gap: 0; position: relative; }
.light-search-city { flex: 1; }
.light-search-city__label { font-size: 9px; color: rgba(16,20,43,.35); margin-bottom: 2px; }
.light-search-city__val { font-size: 18px; font-weight: 800; color: #10142b; }
.light-search-city__sub { font-size: 9px; color: rgba(16,20,43,.4); }
.light-search-arrow { position: absolute; left: 18%; transform: translateX(-50%); font-size: 14px; color: rgba(16,20,43,.3); background: #fff; border: 1px solid rgba(26,31,94,0.1); border-radius: 50%; width: 26px; height: 26px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.light-search-date { flex: 1; padding-left: 12px; border-left: 1px solid rgba(26,31,94,0.1); }
.light-search-date__label { font-size: 9px; color: rgba(16,20,43,.35); margin-bottom: 2px; }
.light-search-date__val { font-size: 12px; font-weight: 600; color: #10142b; }
.light-search-btn { background: #1a1f5e; color: #fff; font-size: 11px; font-weight: 700; padding: 10px 16px; border-radius: 8px; white-space: nowrap; margin-left: 12px; flex-shrink: 0; }
.light-result-label { padding: 6px 14px; font-size: 10px; color: rgba(16,20,43,.4); }
.light-result-label span { color: #4f46e5; font-weight: 600; }
.light-flight { display: flex; align-items: center; justify-content: space-between; padding: 10px 14px; border-top: 1px solid rgba(26,31,94,0.06); }
.light-flight--active { background: #eef2ff; }
.light-flight__times { display: flex; align-items: center; gap: 10px; }
.light-flight__time { font-size: 16px; font-weight: 700; color: #10142b; }
.light-flight__arrow { font-size: 11px; color: rgba(16,20,43,.3); }
.light-flight__stop { font-size: 9px; color: rgba(16,20,43,.35); text-align: center; }
.light-flight__info { font-size: 10px; color: rgba(16,20,43,.4); }
.light-flight__right { display: flex; align-items: center; gap: 10px; }
.light-flight__price { font-size: 13px; font-weight: 700; color: #4f46e5; }
.light-flight__btn { font-size: 10px; font-weight: 700; padding: 5px 12px; border-radius: 6px; background: #1a1f5e; color: #fff; }
.light-flight--active .light-flight__btn { background: #4f46e5; }
/* 반응형 */
@media (max-width: 1024px) {
.main-solution-card { grid-template-columns: 1fr; }
.main-solution-card-right { min-height: 280px; align-items: flex-start; }
}
@media (max-width: 768px) {
.main-solution-grid { grid-template-columns: 1fr; gap: 16px; }
.main-solution-card-top { padding: 22px 22px 16px; min-height: auto; }
.main-solution-card-title { font-size: 20px; }
.main-solution-card-mockup { min-height: 260px; }
.main-solution-section { padding: 86px 6vw 120px; }
.main-solution-card-left { padding: 28px; }
.main-solution-card-title { font-size: 22px; }
.light-closeup { width: 100%; }
.light-header__nav { display: none; }
}
@media (max-width: 480px) {
.main-solution-card-top { padding: 18px 18px 14px; }
.main-solution-card-title { font-size: 18px; }
.main-solution-card-mockup { min-height: 220px; padding: 16px 16px 0; }
.main-solution-section { padding: 72px 5vw 100px; }
.main-solution-card-left { padding: 22px; }
.main-solution-card-title { font-size: 20px; }
}
/* News */
.main-news-section{position:relative;min-height:100vh;padding:130px 8vw;background:#ffffff;overflow:hidden;}
.main-news-section::before{content:"";position:absolute;left:-18vw;bottom:-24vw;width:52vw;height:52vw;border-radius:50%;background:radial-gradient(circle,rgba(26,31,94,.08),transparent 70%);filter:blur(18px);pointer-events:none;}

Loading…
Cancel
Save