Browse Source

feat : utm/uatm 3번째 섹션 완료

remotes/origin/main
이시연 2 weeks ago
parent
commit
be59569587
  1. BIN
      public/images/utm_intro_drone.png
  2. BIN
      public/images/utm_intro_uam.png
  3. BIN
      public/images/utm_intro_uatm.png
  4. BIN
      public/images/utm_intro_utm.png
  5. 38
      src/css/common.css
  6. 263
      src/pages/utm/IntroPage.jsx

BIN
public/images/utm_intro_drone.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

BIN
public/images/utm_intro_uam.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

BIN
public/images/utm_intro_uatm.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

BIN
public/images/utm_intro_utm.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

38
src/css/common.css

@ -1197,6 +1197,7 @@ body{overflow-x:hidden;}
.utm-evo { display: flex; gap: 80px; align-items: flex-start; padding: 100px 48px; } .utm-evo { display: flex; gap: 80px; align-items: flex-start; padding: 100px 48px; }
.utm-evo__left { flex: 0 0 420px; } .utm-evo__left { flex: 0 0 420px; }
/* .utm-evo__left { flex: 0 0 420px; position: sticky; top: 120px; align-self: flex-start; } */
.utm-evo__eyebrow { font-size: 11px; font-weight: 500; letter-spacing: 2px; color: #E8193C; text-transform: uppercase; display: flex; align-items: center; gap: 8px; margin-bottom: 20px; } .utm-evo__eyebrow { font-size: 11px; font-weight: 500; letter-spacing: 2px; color: #E8193C; text-transform: uppercase; display: flex; align-items: center; gap: 8px; margin-bottom: 20px; }
.utm-evo__eyebrow::before { content: ''; width: 20px; height: 1.5px; background: #E8193C; } .utm-evo__eyebrow::before { content: ''; width: 20px; height: 1.5px; background: #E8193C; }
.utm-evo__title { font-size: 36px; font-weight: 700; line-height: 1.35; color: #111; margin-bottom: 20px; word-break: keep-all; } .utm-evo__title { font-size: 36px; font-weight: 700; line-height: 1.35; color: #111; margin-bottom: 20px; word-break: keep-all; }
@ -1206,24 +1207,31 @@ body{overflow-x:hidden;}
.utm-evo__chip-dot { width: 7px; height: 7px; border-radius: 50%; background: #E8193C; flex-shrink: 0; } .utm-evo__chip-dot { width: 7px; height: 7px; border-radius: 50%; background: #E8193C; flex-shrink: 0; }
.utm-evo__right { flex: 1; } .utm-evo__right { flex: 1; }
.utm-evo__track { display: flex; flex-direction: column; position: relative; } .utm-evo__track { position: relative; }
.utm-evo__track::before { content: ''; position: absolute; left: 50%; top: 0; bottom: 0; width: 1px; background: #EBEBEB; transform: translateX(-50%); z-index: 0; } .utm-evo__line-bg { position: absolute; left: 50%; transform: translateX(-50%); top: 0; bottom: 0; width: 1px; background: #e5e5e5; z-index: 0; }
.utm-evo__item { display: grid; grid-template-columns: 1fr 56px 1fr; align-items: center; padding: 20px 0; } .utm-evo__item { display: grid; grid-template-columns: 1fr 56px 1fr; align-items: center; padding: 40px 0; }
.utm-evo__empty { flex: 1; } .utm-evo__empty { flex: 1; }
.utm-evo__card-wrap--left { padding-right: 28px; } .utm-evo__card-wrap--left { padding-right: 28px; }
.utm-evo__card-wrap--right { padding-left: 28px; } .utm-evo__card-wrap--right { padding-left: 28px; }
.utm-evo__line-fill { position: absolute; left: 50%; transform: translateX(-50%); top: 0; width: 2px; background: linear-gradient(180deg, #C850C0, #4158D0); z-index: 1; }
.utm-evo__dot-wrap { display: flex; justify-content: center; align-items: center; z-index: 1; position: relative; } .utm-evo__dot-wrap { display: flex; justify-content: center; align-items: center; z-index: 1; position: relative; }
.utm-evo__dot { width: 44px; height: 44px; border-radius: 50%; background: #F4F4F6; border: 3px solid #fff; box-shadow: 0 0 0 1.5px #E0E0E0; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 700; color: #bbb; } .utm-evo__dot { width: 44px; height: 44px; border-radius: 50%; background: #fff; border: 1.5px solid #ddd; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 600; color: #999; position: relative; transition: border-color 0.5s ease, color 0.5s ease; }
.utm-evo__item--active .utm-evo__dot { background: #E8193C; box-shadow: 0 0 0 8px rgba(232,25,60,0.1); color: #fff; } .utm-evo__dot::before { content: ''; position: absolute; inset: -2px; border-radius: 50%; background: linear-gradient(135deg, #C850C0, #4158D0); opacity: 0; transition: opacity 0.5s ease; z-index: 0; }
.utm-evo__dot span { position: relative; z-index: 2; }
.utm-evo__card { background: #F8F8FC; border-radius: 14px; padding: 22px 20px; border: 1px solid #EBEBEB; }
.utm-evo__item--active .utm-evo__card { background: #fff; border-color: #E8193C; box-shadow: 0 6px 32px rgba(232,25,60,0.1); } .utm-evo__card { display: flex; flex-direction: row; align-items: center; gap: 20px; border-radius: 12px; border: 1px solid #eee; padding: 20px; transition: border-color 0.4s ease, box-shadow 0.4s ease; }
.utm-evo__card-name { font-size: 17px; font-weight: 700; color: #111; margin-bottom: 6px; } .utm-evo__card-img { width: 120px; height: 120px; object-fit: contain; flex-shrink: 0; }
.utm-evo__item--active .utm-evo__card-name { color: #E8193C; } .utm-evo__card-body { display: flex; flex-direction: column; gap: 8px; }
.utm-evo__card-desc { font-size: 12px; color: #999; line-height: 1.7; }
.utm-evo__item--active .utm-evo__card-desc { color: #555; } .utm-evo__card-name { font-size: 15px; font-weight: 700; color: #111; }
.utm-evo__card-tag { display: inline-block; margin-top: 10px; font-size: 11px; font-weight: 500; color: #bbb; background: #EFEFEF; padding: 3px 10px; border-radius: 20px; } .utm-evo__card-desc { font-size: 13px; color: #666; line-height: 1.6; }
.utm-evo__item--active .utm-evo__card-tag { background: rgba(232,25,60,0.08); color: #E8193C; }
.utm-evo__pal-flag { display: flex; align-items: center; gap: 6px; margin-top: 10px; font-size: 11px; font-weight: 600; color: #E8193C; } .utm-evo__card-tag { display: inline-block; font-size: 11px; padding: 4px 10px; border-radius: 4px; background: #f5f5f5; color: #666; }
.utm-evo__item--highlight .utm-evo__card { border: 1.5px solid var(--navy); box-shadow: 0 4px 24px rgba(26,31,94,0.1); }
.utm-evo__item--highlight .utm-evo__card-name { background: none; -webkit-text-fill-color: var(--navy); color: var(--navy); }
.utm-evo__item--highlight .utm-evo__dot { border-color: transparent; color: #fff; }
.utm-evo__item--highlight .utm-evo__dot::before { opacity: 1; }
.utm-evo__item--highlight .utm-evo__card-tag { background: rgba(26,31,94,0.08); color: var(--navy); }

263
src/pages/utm/IntroPage.jsx

@ -1,8 +1,7 @@
import { useRef } from "react"; import { useRef } from "react";
import SubHero from "../../components/SubHero"; import SubHero from "../../components/SubHero";
import useFadeIn from "../../hooks/useFadeIn"; import useFadeIn from "../../hooks/useFadeIn";
import { motion, useInView, useScroll, useTransform } from "framer-motion";
import { motion, useInView } from "framer-motion";
import { import {
MapPin, MapPin,
ShieldAlert, ShieldAlert,
@ -24,19 +23,13 @@ const INTRO_CARDS = [
{ label: "데이터 관리", img: `${basePath}/images/utm_intro_icon4.png` }, { label: "데이터 관리", img: `${basePath}/images/utm_intro_icon4.png` },
]; ];
const UTM_WHAT_LIST = [
"실시간 비행체 위치 감시 및 추적",
"AI 기반 충돌 위험 사전 분석·경보",
"기상청 연계 기상 정보 자동 반영",
"동적 공역 설정 및 지오펜싱 관리",
];
const UTM_WHAT_LEFT = [ const UTM_WHAT_LEFT = [
{ icon: MapPin, label: "실시간 위치 감시" }, { icon: MapPin, label: "실시간 위치 감시" },
{ icon: ShieldAlert, label: "충돌 위험 사전 분석" }, { icon: ShieldAlert, label: "충돌 위험 사전 분석" },
{ icon: Cloud, label: "기상 정보 자동 연계" }, { icon: Cloud, label: "기상 정보 자동 연계" },
{ icon: Network, label: "공역 설정·지오펜싱" }, { icon: Network, label: "공역 설정·지오펜싱" },
]; ];
const UTM_WHAT_RIGHT = [ const UTM_WHAT_RIGHT = [
{ icon: FileCheck, label: "비행 계획 및 경로 승인" }, { icon: FileCheck, label: "비행 계획 및 경로 승인" },
{ icon: BadgeCheck, label: "불법 기체 실시간 감지" }, { icon: BadgeCheck, label: "불법 기체 실시간 감지" },
@ -44,16 +37,128 @@ const UTM_WHAT_RIGHT = [
{ icon: Layers, label: "UAM·드론 시스템 연동" }, { icon: Layers, label: "UAM·드론 시스템 연동" },
]; ];
const EVO_ITEMS = [
{
img: `${basePath}images/utm_intro_drone.png`,
alt: "DRONE",
name: "DRONE",
desc: "개별 드론 운용 단계. 단순 비행 임무 수행 중심으로 체계적 관리 체계 부재.",
tag: "단일 기체 운용",
side: "left",
active: false,
},
{
img: `${basePath}images/utm_intro_utm.png`,
alt: "UTM",
name: "UTM",
desc: "무인기 교통관리 시스템 도입. 비행 경로 승인·충돌 방지·공역 관리 체계화.",
tag: "공역 관리 시스템",
side: "right",
active: false,
},
{
img: `${basePath}images/utm_intro_uam.png`,
alt: "UAM",
name: "UAM",
desc: "도심항공모빌리티 등장. 유인 eVTOL 기체가 도심 저고도 공역을 비행.",
tag: "도심 항공 모빌리티",
side: "left",
active: false,
},
{
img: `${basePath}images/utm_intro_uatm.png`,
alt: "UATM",
name: "UATM",
desc: "UAM과 UTM의 완전한 통합. 기체 운용부터 관제까지 하나의 플랫폼으로 실현.",
tag: "통합 관제 플랫폼",
side: "right",
active: true,
},
];
function EvoItem({ item, index }) {
const itemRef = useRef(null);
const itemInView = useInView(itemRef, { once: true, margin: "-80px" });
const itemActive = useInView(itemRef, { margin: "-45% 0px -45% 0px" });
return (
<motion.div
ref={itemRef}
className={`utm-evo__item${item.active ? " utm-evo__item--active" : ""}${itemActive ? " utm-evo__item--highlight" : ""}`}
initial={{ opacity: 0, y: 40 }}
animate={itemInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6, ease }}
>
{item.side === "left" ? (
<>
<div className="utm-evo__card-wrap utm-evo__card-wrap--left">
<div className="utm-evo__card">
<img
src={item.img}
alt={item.alt}
className="utm-evo__card-img"
/>
<div className="utm-evo__card-body">
<div className="utm-evo__card-name">{item.name}</div>
<div className="utm-evo__card-desc">{item.desc}</div>
<span className="utm-evo__card-tag">{item.tag}</span>
</div>
</div>
</div>
<div className="utm-evo__dot-wrap">
<div className="utm-evo__dot">
<span>{String(index + 1).padStart(2, "0")}</span>
</div>
</div>
<div className="utm-evo__empty" />
</>
) : (
<>
<div className="utm-evo__empty" />
<div className="utm-evo__dot-wrap">
<div className="utm-evo__dot">
<span>{String(index + 1).padStart(2, "0")}</span>{" "}
{/* 여기 span 추가 */}
</div>
</div>
<div className="utm-evo__card-wrap utm-evo__card-wrap--right">
<div className="utm-evo__card">
<img
src={item.img}
alt={item.alt}
className="utm-evo__card-img"
/>
<div className="utm-evo__card-body">
<div className="utm-evo__card-name">{item.name}</div>
<div className="utm-evo__card-desc">{item.desc}</div>
<span className="utm-evo__card-tag">{item.tag}</span>
</div>
</div>
</div>
</>
)}
</motion.div>
);
}
function IntroPage() { function IntroPage() {
const ref = useFadeIn(); const ref = useFadeIn();
const UTM_NAV = [ const UTM_NAV = [
{ label: "UTM/UATM 소개", to: "/utm/intro" }, { label: "UTM/UATM 소개", to: "/utm/intro" },
{ label: "도입사례", to: "/utm/case" }, { label: "도입사례", to: "/utm/case" },
]; ];
const introRef = useRef(null); const introRef = useRef(null);
const introInView = useInView(introRef, { once: true, margin: "-60px" }); const introInView = useInView(introRef, { once: true, margin: "-60px" });
const whatRef = useRef(null); const whatRef = useRef(null);
const whatInView = useInView(whatRef, { once: true, margin: "-200px" }); const whatInView = useInView(whatRef, { once: true, margin: "-200px" });
const evoRef = useRef(null);
const evoInView = useInView(evoRef, { once: true, margin: "-100px" });
const evoTrackRef = useRef(null);
const { scrollYProgress } = useScroll({
target: evoTrackRef,
offset: ["start center", "end center"],
});
const lineHeight = useTransform(scrollYProgress, [0, 1], ["0%", "100%"]);
return ( return (
<article ref={ref}> <article ref={ref}>
@ -61,19 +166,15 @@ function IntroPage() {
label="UTM/UATM" label="UTM/UATM"
title={ title={
<> <>
{/* <span style={{ color: "#111" }}> </span>
<br /> */}
<em>UTM/UATM</em> <em>UTM/UATM</em>
</> </>
} }
// desc=" PAL Networks UTM/UATM ."
navItems={UTM_NAV} navItems={UTM_NAV}
/> />
<div className="sub-content"> <div className="sub-content">
<div className="inner-wrap"> <div className="inner-wrap">
<section className="utm-intro" ref={introRef}> <section className="utm-intro" ref={introRef}>
{/* ── 상단 텍스트 블록 ── */}
<div className="utm-intro__top"> <div className="utm-intro__top">
<motion.span <motion.span
className="fc-eyebrow" className="fc-eyebrow"
@ -83,7 +184,6 @@ function IntroPage() {
> >
Overview Overview
</motion.span> </motion.span>
<motion.h2 <motion.h2
className="utm-intro__title" className="utm-intro__title"
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
@ -94,7 +194,6 @@ function IntroPage() {
<br /> <br />
<em>도심 항공 관제의 새로운 기준</em>입니다. <em>도심 항공 관제의 새로운 기준</em>입니다.
</motion.h2> </motion.h2>
<motion.p <motion.p
className="utm-intro__desc" className="utm-intro__desc"
initial={{ opacity: 0, y: 16 }} initial={{ opacity: 0, y: 16 }}
@ -108,7 +207,6 @@ function IntroPage() {
</motion.p> </motion.p>
</div> </div>
{/* ── 4개 카드 그리드 ── */}
<ul className="utm-intro__cards"> <ul className="utm-intro__cards">
{INTRO_CARDS.map((card, i) => ( {INTRO_CARDS.map((card, i) => (
<motion.li <motion.li
@ -141,7 +239,6 @@ function IntroPage() {
animate={whatInView ? { opacity: 1, y: 0 } : {}} animate={whatInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8, ease }} transition={{ duration: 0.8, ease }}
> >
{/* 상단 텍스트 */}
<div className="utm-what__top"> <div className="utm-what__top">
<motion.span <motion.span
className="utm-what__eyebrow" className="utm-what__eyebrow"
@ -151,7 +248,6 @@ function IntroPage() {
> >
What is UTM What is UTM
</motion.span> </motion.span>
<motion.h2 <motion.h2
className="utm-what__title" className="utm-what__title"
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
@ -160,7 +256,6 @@ function IntroPage() {
> >
UTM, <em>무엇을 있나요?</em> UTM, <em>무엇을 있나요?</em>
</motion.h2> </motion.h2>
<motion.p <motion.p
className="utm-what__desc" className="utm-what__desc"
initial={{ opacity: 0, y: 16 }} initial={{ opacity: 0, y: 16 }}
@ -168,15 +263,13 @@ function IntroPage() {
transition={{ duration: 0.6, delay: 0.2, ease }} transition={{ duration: 0.6, delay: 0.2, ease }}
> >
UTM은 단순한 관제 시스템을 넘어, 도심 저고도 공역 전체를 UTM은 단순한 관제 시스템을 넘어, 도심 저고도 공역 전체를
디지털로 운영하는 통합 플랫폼입니다. 실시간 감시부터 충돌 위험 디지털로 운영하는 통합 플랫폼입니다. <br />
분석, 기상 연계, 공역 관리까지 비행의 모든 순간을 안전하게 실시간 감시부터 충돌 위험 분석, 기상 연계, 공역 관리까지
연결합니다. 비행의 모든 순간을 안전하게 연결합니다.
</motion.p> </motion.p>
</div> </div>
{/* 3열 바디 */}
<div className="utm-what__body"> <div className="utm-what__body">
{/* 왼쪽 카드 */}
<motion.ul <motion.ul
className="utm-what__cards" className="utm-what__cards"
initial={{ opacity: 0, x: -24 }} initial={{ opacity: 0, x: -24 }}
@ -193,7 +286,6 @@ function IntroPage() {
))} ))}
</motion.ul> </motion.ul>
{/* 가운데 목업 (기존 코드 유지) */}
<motion.div <motion.div
className="utm-what__mockup" className="utm-what__mockup"
initial={{ opacity: 0, y: 24 }} initial={{ opacity: 0, y: 24 }}
@ -206,7 +298,6 @@ function IntroPage() {
backgroundImage: `url(${basePath}images/utm_what_img.png)`, backgroundImage: `url(${basePath}images/utm_what_img.png)`,
}} }}
> >
{/* 빨간 드론 - 공역 빨간 구역 (중앙) */}
<div <div
className="drone drone--1" className="drone drone--1"
style={{ top: "35%", left: "48%" }} style={{ top: "35%", left: "48%" }}
@ -230,7 +321,6 @@ function IntroPage() {
<div className="drone__ping drone__ping--red drone__ping--delay" /> <div className="drone__ping drone__ping--red drone__ping--delay" />
</div> </div>
{/* 파란 드론 - 왼쪽 검은 구역 주위 */}
<div <div
className="drone drone--2" className="drone drone--2"
style={{ top: "25%", left: "22%" }} style={{ top: "25%", left: "22%" }}
@ -254,22 +344,19 @@ function IntroPage() {
<div className="drone__ping drone__ping--blue drone__ping--delay" /> <div className="drone__ping drone__ping--blue drone__ping--delay" />
</div> </div>
{/* 주황 드론 - 오른쪽 분홍 구역 근처 */}
<div <div
className="drone drone--3" className="drone drone--3"
style={{ top: "58%", left: "72%" }} style={{ top: "58%", left: "72%" }}
> >
<div className="drone__badge drone__badge--orange"> <div className="drone__badge drone__badge--orange">
<div className="drone__badge-top"> <div className="drone__badge-top">
<div className="drone__badge-top"> <img
<img src={`${basePath}images/orange_drone.png`}
src={`${basePath}images/orange_drone.png`} alt="drone"
alt="drone" width="16"
width="16" height="16"
height="16" />
/> <span className="drone__badge-conn">LTE</span>
<span className="drone__badge-conn">LTE</span>
</div>
</div> </div>
<span className="drone__badge-id">FPA502</span> <span className="drone__badge-id">FPA502</span>
<span className="drone__badge-status"> <span className="drone__badge-status">
@ -284,7 +371,6 @@ function IntroPage() {
</div> </div>
</motion.div> </motion.div>
{/* 오른쪽 카드 */}
<motion.ul <motion.ul
className="utm-what__cards utm-what__cards--right" className="utm-what__cards utm-what__cards--right"
initial={{ opacity: 0, x: 24 }} initial={{ opacity: 0, x: 24 }}
@ -307,15 +393,20 @@ function IntroPage() {
</motion.div> </motion.div>
</div> </div>
</section> </section>
<div className="inner-wrap"> <div className="inner-wrap">
{/* ── DRONE → UATM 진화 섹션 ── */} {/* ── DRONE → UATM 진화 섹션 ── */}
<section className="utm-evo"> <section className="utm-evo" ref={evoRef}>
<div className="utm-evo__left"> <motion.div
{" "} className="utm-evo__left"
initial={{ opacity: 0, x: -32 }}
animate={evoInView ? { opacity: 1, x: 0 } : {}}
transition={{ duration: 0.7, ease }}
>
<motion.span <motion.span
className="fc-eyebrow" className="fc-eyebrow"
initial={{ opacity: 0, y: 16 }} initial={{ opacity: 0, y: 16 }}
animate={introInView ? { opacity: 1, y: 0 } : {}} animate={evoInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6, ease }} transition={{ duration: 0.6, ease }}
> >
Evolution Evolution
@ -330,86 +421,18 @@ function IntroPage() {
통합 관제하는 UATM으로 진화했습니다. PAL Networks는 변화의 통합 관제하는 UATM으로 진화했습니다. PAL Networks는 변화의
최전선에서 기체와 관제를 함께 운영합니다. 최전선에서 기체와 관제를 함께 운영합니다.
</p> </p>
</div> </motion.div>
<div className="utm-evo__right"> <div className="utm-evo__right">
<div className="utm-evo__track"> <div className="utm-evo__track" ref={evoTrackRef}>
<div className="utm-evo__item"> <div className="utm-evo__line-bg" />
<div className="utm-evo__card-wrap utm-evo__card-wrap--left"> <motion.div
<div className="utm-evo__card"> className="utm-evo__line-fill"
<div className="utm-evo__card-name">🚁 DRONE</div> style={{ height: lineHeight }}
<div className="utm-evo__card-desc"> />
개별 드론 운용 단계. 단순 비행 임무 수행 중심으로 체계적 {EVO_ITEMS.map((item, i) => (
관리 체계 부재. <EvoItem key={item.name} item={item} index={i} />
</div> ))}
<span className="utm-evo__card-tag">단일 기체 운용</span>
</div>
</div>
<div className="utm-evo__dot-wrap">
<div className="utm-evo__dot">01</div>
</div>
<div className="utm-evo__empty" />
</div>
<div className="utm-evo__item">
<div className="utm-evo__empty" />
<div className="utm-evo__dot-wrap">
<div className="utm-evo__dot">02</div>
</div>
<div className="utm-evo__card-wrap utm-evo__card-wrap--right">
<div className="utm-evo__card">
<div className="utm-evo__card-name">📡 UTM</div>
<div className="utm-evo__card-desc">
무인기 교통관리 시스템 도입. 비행 경로 승인·충돌
방지·공역 관리 체계화.
</div>
<span className="utm-evo__card-tag">
공역 관리 시스템
</span>
</div>
</div>
</div>
<div className="utm-evo__item">
<div className="utm-evo__card-wrap utm-evo__card-wrap--left">
<div className="utm-evo__card">
<div className="utm-evo__card-name"> UAM</div>
<div className="utm-evo__card-desc">
도심항공모빌리티 등장. 유인 eVTOL 기체가 도심 저고도
공역을 비행.
</div>
<span className="utm-evo__card-tag">
도심 항공 모빌리티
</span>
</div>
</div>
<div className="utm-evo__dot-wrap">
<div className="utm-evo__dot">03</div>
</div>
<div className="utm-evo__empty" />
</div>
<div className="utm-evo__item utm-evo__item--active">
<div className="utm-evo__empty" />
<div className="utm-evo__dot-wrap">
<div className="utm-evo__dot">04</div>
</div>
<div className="utm-evo__card-wrap utm-evo__card-wrap--right">
<div className="utm-evo__card">
<div className="utm-evo__card-name">🛸 UATM</div>
<div className="utm-evo__card-desc">
UAM과 UTM의 완전한 통합. 기체 운용부터 관제까지 하나의
플랫폼으로 실현.
</div>
<span className="utm-evo__card-tag">
통합 관제 플랫폼
</span>
<div className="utm-evo__pal-flag">
PAL Networks가 실현합니다
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
</section> </section>

Loading…
Cancel
Save