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. 적용 분야
*/
.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:hover { border-color: var(--color-primary-border); box-shadow: 0 8px 28px var(--color-primary-shadow); }
.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 { flex: 1.6; }
.fc-domain-card__img { width: 100%; aspect-ratio: 16/10; overflow: hidden; }
.fc-domain-card__img img { width: 100%; height: 100%; object-fit: cover; transition: transform .4s ease; }
.fc-domain-card:hover .fc-domain-card__img img { transform: scale(1.05); }
.fc-domain-card__img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 0.5s ease; }
.fc-domain-card:hover .fc-domain-card__img { transform: scale(1.08); }
.fc-domain-card__body { display: flex; flex-direction: column; gap: .5rem; padding: 1.25rem 1.25rem 1.5rem; }
.fc-domain-card__label { font-size: .88rem; font-weight: 700; color: var(--color-primary); line-height: 1.3; }
.fc-domain-card__desc { font-size: .78rem; line-height: 1.65; color: #888; margin: 0; }
.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: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%); }
@media (max-width: 1024px) { .fc-domains__grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 640px) { .fc-domains__grid { grid-template-columns: repeat(2, 1fr); } }
.fc-domain-card__label { font-size: 1.125rem; font-weight: 700; color: #fff; line-height: 1.3; }
.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. 주요기능
*/

230
src/pages/solution/FlightControlPage.jsx

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

Loading…
Cancel
Save