Browse Source

적용분야 css수정

remotes/origin/main
김지은 3 weeks ago
parent
commit
0fa84c74a8
  1. 25
      src/css/common.css
  2. 230
      src/pages/solution/FlightControlPage.jsx

25
src/css/common.css

@ -735,21 +735,24 @@ body{overflow-x:hidden;}
5. 적용 분야 5. 적용 분야
*/ */
.fc-domains { margin-bottom: 8rem; } .fc-domains { margin-bottom: 8rem; }
.fc-domains__grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 1.25rem; } .fc-domains__grid { display: flex; gap: 1.25rem; height: 420px; }
.fc-domain-card { display: flex; flex-direction: column; border: 1px solid var(--color-primary-soft-border); border-radius: 1rem; background: #fff; overflow: hidden; transition: border-color .2s, box-shadow .2s; cursor: default; } .fc-domain-card { position: relative; border-radius: 1rem; overflow: hidden; flex: 1; cursor: default; transition: flex 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94); }
.fc-domain-card:hover { border-color: var(--color-primary-border); box-shadow: 0 8px 28px var(--color-primary-shadow); } .fc-domain-card:hover { flex: 1.6; }
.fc-domain-card__img { width: 100%; aspect-ratio: 16/10; overflow: hidden; } .fc-domain-card__img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 0.5s ease; }
.fc-domain-card__img img { width: 100%; height: 100%; object-fit: cover; transition: transform .4s ease; } .fc-domain-card:hover .fc-domain-card__img { transform: scale(1.08); }
.fc-domain-card:hover .fc-domain-card__img img { transform: scale(1.05); }
.fc-domain-card__body { display: flex; flex-direction: column; gap: .5rem; padding: 1.25rem 1.25rem 1.5rem; } .fc-domain-card__overlay { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: flex-end; padding: 1.25rem; background: linear-gradient(to top, rgba(0,0,0,.72) 0%, rgba(0,0,0,.18) 45%, transparent 100%); transition: background 0.4s ease; }
.fc-domain-card__label { font-size: .88rem; font-weight: 700; color: var(--color-primary); line-height: 1.3; } .fc-domain-card:hover .fc-domain-card__overlay { background: linear-gradient(to top, rgba(0,0,0,.88) 0%, rgba(0,0,0,.5) 50%, rgba(0,0,0,.15) 100%); }
.fc-domain-card__desc { font-size: .78rem; line-height: 1.65; color: #888; margin: 0; }
@media (max-width: 1024px) { .fc-domains__grid { grid-template-columns: repeat(3, 1fr); } } .fc-domain-card__label { font-size: 1.125rem; font-weight: 700; color: #fff; line-height: 1.3; }
@media (max-width: 640px) { .fc-domains__grid { grid-template-columns: repeat(2, 1fr); } }
.fc-domain-card__desc { font-size: .8rem; line-height: 1.65; color: rgba(255,255,255,.85); margin: .5rem 0 0; max-height: 0; opacity: 0; overflow: hidden; transform: translateY(8px); transition: max-height 0.4s ease, opacity 0.35s ease, transform 0.35s ease; }
.fc-domain-card:hover .fc-domain-card__desc { max-height: 6rem; opacity: 1; transform: translateY(0); }
@media (max-width: 1024px) { .fc-domains__grid { flex-wrap: wrap; height: auto; } .fc-domain-card { flex: 0 0 calc(33.33% - 1rem); aspect-ratio: 3/4; } }
@media (max-width: 640px) { .fc-domain-card { flex: 0 0 calc(50% - 0.625rem); } }
/* /*
6. 주요기능 6. 주요기능
*/ */

230
src/pages/solution/FlightControlPage.jsx

@ -1,18 +1,6 @@
import { useRef, useState } from "react"; import { useRef, useState } from "react";
import { motion, useInView, AnimatePresence } from "framer-motion"; import { motion, useInView, AnimatePresence } from "framer-motion";
import { import { Radio, Puzzle, Network, Expand, Shield, ArrowUpRight, Package, Wind, AlertTriangle, Ship, Plane } from "lucide-react";
Radio,
Puzzle,
Network,
Expand,
Shield,
ArrowUpRight,
Package,
Wind,
AlertTriangle,
Ship,
Plane,
} from "lucide-react";
import SubHero from "../../components/SubHero"; import SubHero from "../../components/SubHero";
import useFadeIn from "../../hooks/useFadeIn"; import useFadeIn from "../../hooks/useFadeIn";
@ -100,12 +88,7 @@ const ease = [0.22, 1, 0.36, 1];
function RevealText({ children, delay = 0, className }) { function RevealText({ children, delay = 0, className }) {
return ( return (
<div style={{ overflow: "hidden" }}> <div style={{ overflow: "hidden" }}>
<motion.div <motion.div className={className} initial={{ y: "105%", opacity: 0 }} animate={{ y: "0%", opacity: 1 }} transition={{ duration: 0.75, ease: [0.22, 1, 0.36, 1], delay }}>
className={className}
initial={{ y: "105%", opacity: 0 }}
animate={{ y: "0%", opacity: 1 }}
transition={{ duration: 0.75, ease: [0.22, 1, 0.36, 1], delay }}
>
{children} {children}
</motion.div> </motion.div>
</div> </div>
@ -115,10 +98,7 @@ function RevealText({ children, delay = 0, className }) {
function StaggerWords({ text, delay = 0, className }) { function StaggerWords({ text, delay = 0, className }) {
const words = text.split(" "); const words = text.split(" ");
return ( return (
<span <span className={className} style={{ display: "flex", flexWrap: "wrap", gap: "0 .3em" }}>
className={className}
style={{ display: "flex", flexWrap: "wrap", gap: "0 .3em" }}
>
{words.map((word, i) => ( {words.map((word, i) => (
<span key={i} style={{ overflow: "hidden", display: "inline-block" }}> <span key={i} style={{ overflow: "hidden", display: "inline-block" }}>
<motion.span <motion.span
@ -168,11 +148,7 @@ function FlightControlPage() {
return ( return (
<article ref={ref}> <article ref={ref}>
<SubHero <SubHero label="SOLUTION" title={<em>Flight Management</em>} navItems={SOLUTION_NAV} />
label="SOLUTION"
title={<em>Flight Management</em>}
navItems={SOLUTION_NAV}
/>
<div className="sub-content"> <div className="sub-content">
<div className="inner-wrap"> <div className="inner-wrap">
@ -245,40 +221,19 @@ function FlightControlPage() {
{/* 개요 인트로 */} {/* 개요 인트로 */}
<section className="fc-intro" ref={introRef}> <section className="fc-intro" ref={introRef}>
<div className="fc-intro__left"> <div className="fc-intro__left">
<motion.span <motion.span className="fc-eyebrow" initial={{ opacity: 0, y: 16 }} animate={introInView ? { opacity: 1, y: 0 } : {}} transition={{ duration: 0.6, ease }}>
className="fc-eyebrow"
initial={{ opacity: 0, y: 16 }}
animate={introInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6, ease }}
>
Overview Overview
</motion.span> </motion.span>
<motion.h2 <motion.h2 className="fc-intro__title" initial={{ opacity: 0, y: 24 }} animate={introInView ? { opacity: 1, y: 0 } : {}} transition={{ duration: 0.7, ease, delay: 0.1 }}>
className="fc-intro__title"
initial={{ opacity: 0, y: 24 }}
animate={introInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.7, ease, delay: 0.1 }}
>
모든 이동체 정보를 모든 이동체 정보를
<br /> <br />
하나의 플랫폼에서 하나의 플랫폼에서
</motion.h2> </motion.h2>
<motion.p <motion.p className="fc-intro__desc" initial={{ opacity: 0, y: 16 }} animate={introInView ? { opacity: 1, y: 0 } : {}} transition={{ duration: 0.6, ease, delay: 0.2 }}>
className="fc-intro__desc" 항공기, 무인기, 선박, 지상 이동체의 실시간 정보를 통합 모니터링하고 <br />
initial={{ opacity: 0, y: 16 }}
animate={introInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6, ease, delay: 0.2 }}
>
항공기, 무인기, 선박, 지상 이동체의 실시간 정보를 통합
모니터링하고 <br />
상황을 인식하여 신속하고 안전한 운영 의사결정을 지원합니다. 상황을 인식하여 신속하고 안전한 운영 의사결정을 지원합니다.
</motion.p> </motion.p>
<motion.div <motion.div className="fc-intro__icons" initial={{ opacity: 0, y: 16 }} animate={introInView ? { opacity: 1, y: 0 } : {}} transition={{ duration: 0.6, ease, delay: 0.3 }}>
className="fc-intro__icons"
initial={{ opacity: 0, y: 16 }}
animate={introInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6, ease, delay: 0.3 }}
>
{[ {[
{ img: "fc_aircraft.png", label: "항공기" }, { img: "fc_aircraft.png", label: "항공기" },
{ img: "fc_drone.png", label: "무인기" }, { img: "fc_drone.png", label: "무인기" },
@ -286,27 +241,15 @@ function FlightControlPage() {
{ img: "fc_car.png", label: "차량 등" }, { img: "fc_car.png", label: "차량 등" },
].map((item, i) => ( ].map((item, i) => (
<div key={i} className="fc-intro__icon-item"> <div key={i} className="fc-intro__icon-item">
<img <img src={`${basePath}images/${item.img}`} alt={item.label} />
src={`${basePath}images/${item.img}`}
alt={item.label}
/>
<span>{item.label}</span> <span>{item.label}</span>
</div> </div>
))} ))}
</motion.div> </motion.div>
</div> </div>
<motion.div <motion.div className="fc-intro__right" initial={{ opacity: 0, x: 40 }} animate={introInView ? { opacity: 1, x: 0 } : {}} transition={{ duration: 0.9, ease, delay: 0.15 }}>
className="fc-intro__right" <img src={`${basePath}images/fc_computer.png`} alt="비행상황관리 시스템" className="fc-intro__monitor" />
initial={{ opacity: 0, x: 40 }}
animate={introInView ? { opacity: 1, x: 0 } : {}}
transition={{ duration: 0.9, ease, delay: 0.15 }}
>
<img
src={`${basePath}images/fc_computer.png`}
alt="비행상황관리 시스템"
className="fc-intro__monitor"
/>
</motion.div> </motion.div>
</section> </section>
@ -359,13 +302,7 @@ function FlightControlPage() {
icons: null, icons: null,
}, },
].map((item, i) => ( ].map((item, i) => (
<motion.div <motion.div key={i} className="fc-highlight__item" initial={{ opacity: 0, y: 40 }} animate={highlightInView ? { opacity: 1, y: 0 } : {}} transition={{ duration: 0.7, ease, delay: i * 0.15 }}>
key={i}
className="fc-highlight__item"
initial={{ opacity: 0, y: 40 }}
animate={highlightInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.7, ease, delay: i * 0.15 }}
>
<div className="fc-highlight__text"> <div className="fc-highlight__text">
<span className="fc-eyebrow">{item.tag}</span> <span className="fc-eyebrow">{item.tag}</span>
<h3 className="fc-highlight__title"> <h3 className="fc-highlight__title">
@ -380,11 +317,7 @@ function FlightControlPage() {
</div> </div>
<div className="fc-highlight__img-wrap"> <div className="fc-highlight__img-wrap">
<div className="fc-highlight__img-scene"> <div className="fc-highlight__img-scene">
<img <img src={`${basePath}images/${item.img}`} alt={item.tag} className="fc-highlight__tablet" />
src={`${basePath}images/${item.img}`}
alt={item.tag}
className="fc-highlight__tablet"
/>
{item.icons && {item.icons &&
item.icons.map((icon, j) => ( item.icons.map((icon, j) => (
<motion.img <motion.img
@ -394,11 +327,7 @@ function FlightControlPage() {
className="fc-highlight__float-icon" className="fc-highlight__float-icon"
style={{ left: icon.x, top: icon.y }} style={{ left: icon.x, top: icon.y }}
initial={{ x: 0, y: 0 }} initial={{ x: 0, y: 0 }}
animate={ animate={highlightInView ? { x: icon.move.x[1], y: icon.move.y[1] } : { x: 0, y: 0 }}
highlightInView
? { x: icon.move.x[1], y: icon.move.y[1] }
: { x: 0, y: 0 }
}
transition={{ transition={{
duration: 2.5, duration: 2.5,
repeat: 0, repeat: 0,
@ -410,30 +339,9 @@ function FlightControlPage() {
{i === 1 && ( {i === 1 && (
<> <>
<motion.img <motion.img src={`${basePath}images/fc_left_tab.png`} alt="" className="fc-situation__left" initial={{ opacity: 0, x: -30 }} animate={highlightInView ? { opacity: 1, x: 0 } : {}} transition={{ duration: 0.8, ease, delay: 0.3 }} />
src={`${basePath}images/fc_left_tab.png`} <motion.img src={`${basePath}images/fc_right_tab.png`} alt="" className="fc-situation__right" initial={{ opacity: 0, x: 30 }} animate={highlightInView ? { opacity: 1, x: 0 } : {}} transition={{ duration: 0.8, ease, delay: 0.5 }} />
alt="" <motion.img src={`${basePath}images/fc_bottom_tab.png`} alt="" className="fc-situation__bottom" initial={{ opacity: 0, y: 30 }} animate={highlightInView ? { opacity: 1, y: 0 } : {}} transition={{ duration: 0.8, ease, delay: 0.7 }} />
className="fc-situation__left"
initial={{ opacity: 0, x: -30 }}
animate={highlightInView ? { opacity: 1, x: 0 } : {}}
transition={{ duration: 0.8, ease, delay: 0.3 }}
/>
<motion.img
src={`${basePath}images/fc_right_tab.png`}
alt=""
className="fc-situation__right"
initial={{ opacity: 0, x: 30 }}
animate={highlightInView ? { opacity: 1, x: 0 } : {}}
transition={{ duration: 0.8, ease, delay: 0.5 }}
/>
<motion.img
src={`${basePath}images/fc_bottom_tab.png`}
alt=""
className="fc-situation__bottom"
initial={{ opacity: 0, y: 30 }}
animate={highlightInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8, ease, delay: 0.7 }}
/>
</> </>
)} )}
</div> </div>
@ -459,28 +367,14 @@ function FlightControlPage() {
{/* 3. 적용 분야 */} {/* 3. 적용 분야 */}
<section className="fc-domains" ref={domainsRef}> <section className="fc-domains" ref={domainsRef}>
<motion.span <motion.span className="fc-section-title" initial={{ opacity: 0, y: 20 }} animate={domainsInView ? { opacity: 1, y: 0 } : {}} transition={{ duration: 0.6, ease }}>
className="fc-section-title"
initial={{ opacity: 0, y: 20 }}
animate={domainsInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6, ease }}
>
적용 분야 적용 분야
</motion.span> </motion.span>
<div className="fc-domains__grid"> <div className="fc-domains__grid">
{DOMAINS.map(({ icon: Icon, img, label, desc }, i) => ( {DOMAINS.map(({ icon: Icon, img, label, desc }, i) => (
<motion.div <motion.div key={label} className="fc-domain-card" initial={{ opacity: 0, y: 24 }} animate={domainsInView ? { opacity: 1, y: 0 } : {}} transition={{ duration: 0.55, ease, delay: 0.07 * i }}>
key={label} <img className="fc-domain-card__img" src={`${basePath}images/${img}`} alt={label} />
className="fc-domain-card" <div className="fc-domain-card__overlay">
initial={{ opacity: 0, y: 24 }}
animate={domainsInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.55, ease, delay: 0.07 * i }}
whileHover={{ y: -4, transition: { duration: 0.2 } }}
>
<div className="fc-domain-card__img">
<img src={`${basePath}images/${img}`} alt={label} />
</div>
<div className="fc-domain-card__body">
<span className="fc-domain-card__label">{label}</span> <span className="fc-domain-card__label">{label}</span>
<p className="fc-domain-card__desc">{desc}</p> <p className="fc-domain-card__desc">{desc}</p>
</div> </div>
@ -488,81 +382,34 @@ function FlightControlPage() {
))} ))}
</div> </div>
</section> </section>
{/* 4. 주요기능 */} {/* 4. 주요기능 */}
<section className="fc-functions" ref={funcRef}> <section className="fc-functions" ref={funcRef}>
<motion.span <motion.span className="fc-section-title" initial={{ opacity: 0, y: 20 }} animate={funcInView ? { opacity: 1, y: 0 } : {}} transition={{ duration: 0.6, ease }}>
className="fc-section-title"
initial={{ opacity: 0, y: 20 }}
animate={funcInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6, ease }}
>
주요기능 주요기능
</motion.span> </motion.span>
<div className="fc-functions__body"> <div className="fc-functions__body">
<ul className="fc-func-list"> <ul className="fc-func-list">
{FUNCTIONS.map(({ num, label }, i) => ( {FUNCTIONS.map(({ num, label }, i) => (
<motion.li <motion.li key={num} className={`fc-func-item${activeIdx === i ? " is-active" : ""}`} onMouseEnter={() => setActiveIdx(i)} initial={{ opacity: 0, y: 16 }} animate={funcInView ? { opacity: 1, y: 0 } : {}} transition={{ duration: 0.5, ease, delay: 0.05 * i }}>
key={num}
className={`fc-func-item${activeIdx === i ? " is-active" : ""}`}
onMouseEnter={() => setActiveIdx(i)}
initial={{ opacity: 0, y: 16 }}
animate={funcInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.5, ease, delay: 0.05 * i }}
>
<span className="fc-func-item__num">{num}</span> <span className="fc-func-item__num">{num}</span>
<span className="fc-func-item__label">{label}</span> <span className="fc-func-item__label">{label}</span>
<motion.span <motion.span className="fc-func-item__arrow" initial={{ opacity: 0, x: -6 }} animate={activeIdx === i ? { opacity: 1, x: 0 } : { opacity: 0, x: -6 }} transition={{ duration: 0.2 }}>
className="fc-func-item__arrow"
initial={{ opacity: 0, x: -6 }}
animate={
activeIdx === i
? { opacity: 1, x: 0 }
: { opacity: 0, x: -6 }
}
transition={{ duration: 0.2 }}
>
<ArrowUpRight size={16} strokeWidth={1.5} /> <ArrowUpRight size={16} strokeWidth={1.5} />
</motion.span> </motion.span>
<motion.div <motion.div className="fc-func-item__line" animate={{ scaleX: activeIdx === i ? 1 : 0 }} transition={{ duration: 0.35, ease }} />
className="fc-func-item__line"
animate={{ scaleX: activeIdx === i ? 1 : 0 }}
transition={{ duration: 0.35, ease }}
/>
</motion.li> </motion.li>
))} ))}
</ul> </ul>
<div className="fc-func-display"> <div className="fc-func-display">
<AnimatePresence mode="wait"> <AnimatePresence mode="wait">
<motion.div <motion.div key={activeIdx} className="fc-func-display__inner" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} transition={{ duration: 0.35, ease: "easeInOut" }}>
key={activeIdx} <img src={FUNCTIONS[activeIdx].img} alt={FUNCTIONS[activeIdx].label} className="fc-func-display__img" />
className="fc-func-display__inner"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.35, ease: "easeInOut" }}
>
<img
src={FUNCTIONS[activeIdx].img}
alt={FUNCTIONS[activeIdx].label}
className="fc-func-display__img"
/>
<div className="fc-func-display__caption"> <div className="fc-func-display__caption">
<motion.span <motion.span key={`num-${activeIdx}`} className="fc-func-display__num" initial={{ opacity: 0, y: 6 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.25 }}>
key={`num-${activeIdx}`}
className="fc-func-display__num"
initial={{ opacity: 0, y: 6 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.25 }}
>
{FUNCTIONS[activeIdx].num} {FUNCTIONS[activeIdx].num}
</motion.span> </motion.span>
<motion.span <motion.span key={`label-${activeIdx}`} className="fc-func-display__label" initial={{ opacity: 0, y: 6 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.25, delay: 0.05 }}>
key={`label-${activeIdx}`}
className="fc-func-display__label"
initial={{ opacity: 0, y: 6 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.25, delay: 0.05 }}
>
{FUNCTIONS[activeIdx].label} {FUNCTIONS[activeIdx].label}
</motion.span> </motion.span>
</div> </div>
@ -574,23 +421,12 @@ function FlightControlPage() {
{/* 5. 시스템 구성 흐름 */} {/* 5. 시스템 구성 흐름 */}
<section className="fc-flow" ref={flowRef}> <section className="fc-flow" ref={flowRef}>
<motion.span <motion.span className="fc-section-title" initial={{ opacity: 0, y: 20 }} animate={flowInView ? { opacity: 1, y: 0 } : {}} transition={{ duration: 0.6, ease }}>
className="fc-section-title"
initial={{ opacity: 0, y: 20 }}
animate={flowInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6, ease }}
>
시스템 구성 시스템 구성
</motion.span> </motion.span>
<div className="fc-flow__row"> <div className="fc-flow__row">
{FLOW.map(({ step, label, desc }, i) => ( {FLOW.map(({ step, label, desc }, i) => (
<motion.div <motion.div key={step} className="fc-flow__item" initial={{ opacity: 0, y: 20 }} animate={flowInView ? { opacity: 1, y: 0 } : {}} transition={{ duration: 0.5, ease, delay: 0.08 * i }}>
key={step}
className="fc-flow__item"
initial={{ opacity: 0, y: 20 }}
animate={flowInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.5, ease, delay: 0.08 * i }}
>
<span className="fc-flow__step">{step}</span> <span className="fc-flow__step">{step}</span>
<span className="fc-flow__label">{label}</span> <span className="fc-flow__label">{label}</span>
<p className="fc-flow__desc">{desc}</p> <p className="fc-flow__desc">{desc}</p>

Loading…
Cancel
Save