diff --git a/public/images/mt_icon01.png b/public/images/mt_icon01.png new file mode 100644 index 0000000..0be8f44 Binary files /dev/null and b/public/images/mt_icon01.png differ diff --git a/public/images/mt_icon02.png b/public/images/mt_icon02.png new file mode 100644 index 0000000..f9a8987 Binary files /dev/null and b/public/images/mt_icon02.png differ diff --git a/public/images/mt_icon03.png b/public/images/mt_icon03.png new file mode 100644 index 0000000..c03cfe9 Binary files /dev/null and b/public/images/mt_icon03.png differ diff --git a/public/images/mt_icon04.png b/public/images/mt_icon04.png new file mode 100644 index 0000000..cdb9595 Binary files /dev/null and b/public/images/mt_icon04.png differ diff --git a/public/images/mt_icon05.png b/public/images/mt_icon05.png new file mode 100644 index 0000000..119d38f Binary files /dev/null and b/public/images/mt_icon05.png differ diff --git a/src/css/common.css b/src/css/common.css index 6d0933d..4076549 100644 --- a/src/css/common.css +++ b/src/css/common.css @@ -1009,4 +1009,120 @@ body{overflow-x:hidden;} .si_archive__title { font-size: 30px; } .si_archive__desc { font-size: 13px; } .si_archive__progress { gap: 8px; } +} + + +/* ════════════════════════════════ + MaintenancePage (mt-) +════════════════════════════════ */ + +/* ── 인트로 ── */ +.mt-intro {display:flex;gap:80px;align-items:flex-start;padding:80px 0 100px;} +.mt-intro__left {flex:0 0 420px;} +.mt-intro__right {flex:1;min-width:0;padding-top:8px;} + +.mt-title-line {overflow:hidden;padding-bottom:.06em;margin-bottom:-.06em;} +.mt-intro__title {font-size:clamp(26px,2.8vw,38px);font-weight:800;color:var(--color-primary);line-height:1.3;letter-spacing:-.03em;margin:0;} + +.mt-intro__desc {font-size:.9rem;color:#666;line-height:1.9;margin:28px 0 36px;word-break:keep-all;} + +.mt-intro__cta {display:inline-flex;align-items:center;gap:8px;font-size:.88rem;font-weight:700;color:var(--pink);text-decoration:none;letter-spacing:-.01em;transition:gap .25s;} +.mt-intro__cta:hover {gap:14px;} + +/* ── Quote 카드 ── */ +.mt-quote {position:relative;margin-top:40px;padding:32px 28px 28px;border-radius:20px;background:var(--color-primary);overflow:hidden;} +.mt-quote::before {content:'';position:absolute;inset:0;background:var(--grad-brand);opacity:.18;pointer-events:none;} +.mt-quote::after {content:'';position:absolute;inset:0;background-image:radial-gradient(rgba(255,255,255,.07) 1px,transparent 1px);background-size:18px 18px;pointer-events:none;} +.mt-quote__mark {position:relative;z-index:1;font-size:2.5rem;font-weight:900;color:var(--pink);line-height:1;margin-bottom:12px;} +.mt-quote__text {position:relative;z-index:1;font-size:1.05rem;font-weight:700;color:#fff;line-height:1.65;letter-spacing:-.02em;margin:0 0 20px;} +.mt-quote__brand {position:relative;z-index:1;font-size:.72rem;font-weight:600;color:rgba(255,255,255,.35);letter-spacing:.12em;text-transform:uppercase;} + +/* ── 서비스 리스트 ── */ +.mt-svc-list {list-style:none;margin:0;padding:0;} +.mt-svc-item {position:relative;display:flex;align-items:center;gap:24px;padding:20px 0;border-top:1px solid var(--color-primary-soft-border);cursor:default;overflow:hidden;transition:padding-left .35s cubic-bezier(.22,1,.36,1);} +.mt-svc-list li:last-child {border-bottom:1px solid var(--color-primary-soft-border);} +.mt-svc-item:hover, .mt-svc-item.is-active {padding-left:12px;} + +.mt-svc-item__num {font-size:.7rem;font-weight:800;letter-spacing:.1em;color:var(--color-primary-border-strong);flex-shrink:0;width:28px;transition:color .3s;} +.mt-svc-item:hover .mt-svc-item__num, .mt-svc-item.is-active .mt-svc-item__num {color:var(--pink);} + +.mt-svc-item__body {flex:1;min-width:0;} +.mt-svc-item__title {display:block;font-size:1rem;font-weight:700;color:#bbb;letter-spacing:-.01em;transition:color .3s;} +.mt-svc-item:hover .mt-svc-item__title, .mt-svc-item.is-active .mt-svc-item__title {color:var(--color-primary);} +.mt-svc-item__desc {display:block;font-size:.78rem;color:#bbb;line-height:1.5;margin-top:4px;max-height:0;opacity:0;overflow:hidden;transform:translateY(4px);transition:max-height .35s ease, opacity .3s ease, transform .3s ease;} +.mt-svc-item:hover .mt-svc-item__desc, .mt-svc-item.is-active .mt-svc-item__desc {max-height:3rem;opacity:1;transform:translateY(0);} + +.mt-svc-item__icon-wrap {flex-shrink:0;width:64px;height:64px;display:flex;align-items:center;justify-content:center;opacity:0;transform:scale(.85) translateX(8px);transition:opacity .35s ease, transform .35s cubic-bezier(.22,1,.36,1);} +.mt-svc-item:hover .mt-svc-item__icon-wrap, .mt-svc-item.is-active .mt-svc-item__icon-wrap {opacity:1;transform:scale(1) translateX(0);} +.mt-svc-item__icon {width:100%;height:100%;object-fit:contain;} + +.mt-svc-item__bar {position:absolute;bottom:0;left:0;right:0;height:1px;background:var(--grad-brand-h);transform:scaleX(0);transform-origin:left;transition:transform .4s cubic-bezier(.22,1,.36,1);} +.mt-svc-item:hover .mt-svc-item__bar, .mt-svc-item.is-active .mt-svc-item__bar {transform:scaleX(1);} + +/* ── KPI 바 ── */ +.mt-kpi {background:var(--color-primary);padding:56px 0;margin:0 0 100px;} +.mt-kpi__grid {display:grid;grid-template-columns:repeat(4,1fr);gap:0;} +.mt-kpi__item {display:flex;flex-direction:column;align-items:center;gap:8px;padding:20px 16px;border-right:1px solid rgba(255,255,255,.1);text-align:center;transition:background .2s;} +.mt-kpi__item:last-child {border-right:none;} +.mt-kpi__item:hover {background:rgba(255,255,255,.05);} +.mt-kpi__icon {font-size:1.4rem;margin-bottom:4px;opacity:.7;} +.mt-kpi__value {font-size:clamp(28px,3.5vw,48px);font-weight:900;color:#fff;letter-spacing:-.04em;line-height:1;} +.mt-kpi__label {font-size:.78rem;font-weight:500;color:rgba(255,255,255,.45);line-height:1.4;} + +/* ── 5컬럼 서비스 ── */ +.mt-services {padding-bottom:120px;} +.mt-services__grid {display:grid;grid-template-columns:repeat(5,1fr);gap:0;border:1px solid var(--color-primary-soft-border);border-radius:16px;overflow:hidden;margin-top:40px;} + +.mt-service-card {position:relative;display:flex;flex-direction:column;gap:12px;padding:32px 24px 28px;border-right:1px solid var(--color-primary-soft-border);overflow:hidden;transition:background .25s;} +.mt-service-card:last-child {border-right:none;} +.mt-service-card:hover {background:var(--color-primary-soft);} + +.mt-service-card__img-wrap {width:72px;height:72px;margin-bottom:8px;flex-shrink:0;transition:transform .4s cubic-bezier(.22,1,.36,1);} +.mt-service-card:hover .mt-service-card__img-wrap {transform:translateY(-6px) scale(1.06);} +.mt-service-card__img {width:100%;height:100%;object-fit:contain;} +/* 이미지 파일명: mt_icon01.png ~ mt_icon05.png */ + +.mt-service-card__num {font-size:.7rem;font-weight:800;letter-spacing:.12em;color:var(--pink);opacity:.7;} +.mt-service-card__title {font-size:1rem;font-weight:800;color:var(--color-primary);letter-spacing:-.02em;margin:0;} +.mt-service-card__desc {font-size:.78rem;color:#888;line-height:1.7;word-break:keep-all;margin:0;} + +.mt-service-card__line {position:absolute;bottom:0;left:0;right:0;height:2px;background:var(--grad-brand-h);transform:scaleX(0);transform-origin:left;transition:transform .4s cubic-bezier(.22,1,.36,1);} +.mt-service-card:hover .mt-service-card__line {transform:scaleX(1);} + +/* ── Responsive ── */ +@media (max-width: 1280px) { + .mt-intro {gap:56px;} + .mt-intro__left {flex:0 0 360px;} +} + +@media (max-width: 1024px) { + .mt-intro {flex-direction:column;gap:48px;padding:60px 0 80px;} + .mt-intro__left {flex:none;width:100%;} + .mt-services__grid {grid-template-columns:repeat(3,1fr);} + .mt-service-card:nth-child(3) {border-right:none;} + .mt-service-card:nth-child(4), .mt-service-card:nth-child(5) {border-top:1px solid var(--color-primary-soft-border);} + .mt-service-card:nth-child(5) {border-right:none;} + .mt-kpi__grid {grid-template-columns:repeat(2,1fr);} + .mt-kpi__item:nth-child(2) {border-right:none;} + .mt-kpi__item:nth-child(3), .mt-kpi__item:nth-child(4) {border-top:1px solid rgba(255,255,255,.1);} + .mt-kpi__item:nth-child(4) {border-right:none;} +} + +@media (max-width: 768px) { + .mt-intro {padding:48px 0 64px;} + .mt-intro__title {font-size:clamp(22px,6vw,30px);} + .mt-services__grid {grid-template-columns:repeat(2,1fr);} + .mt-service-card:nth-child(2n) {border-right:none;} + .mt-service-card:nth-child(3) {border-right:1px solid var(--color-primary-soft-border);} + .mt-service-card:nth-child(n+3) {border-top:1px solid var(--color-primary-soft-border);} + .mt-service-card:nth-child(5) {border-right:none;grid-column:span 2;} + .mt-kpi {margin-bottom:64px;} +} + +@media (max-width: 480px) { + .mt-services__grid {grid-template-columns:1fr;} + .mt-service-card {border-right:none !important;} + .mt-service-card:nth-child(n+2) {border-top:1px solid var(--color-primary-soft-border);} + .mt-service-card:nth-child(5) {grid-column:span 1;} + .mt-kpi__grid {grid-template-columns:repeat(2,1fr);} } \ No newline at end of file diff --git a/src/pages/business/MaintenancePage.jsx b/src/pages/business/MaintenancePage.jsx index da78339..9fbc2a8 100644 --- a/src/pages/business/MaintenancePage.jsx +++ b/src/pages/business/MaintenancePage.jsx @@ -1,46 +1,200 @@ +import { useRef, useState, useEffect } from "react"; +import { motion, useInView, animate } from "framer-motion"; import SubHero from "../../components/SubHero"; import useFadeIn from "../../hooks/useFadeIn"; -import { useRef } from "react"; -import { motion, useInView } from "framer-motion"; + +const ease = [0.22, 1, 0.36, 1]; + +const BUSINESS_NAV = [ + { label: "System Integration", to: "/business/si" }, + { label: "R&D", to: "/business/rnd" }, + { label: "운영 · 유지보수", to: "/business/maintenance" }, +]; + +const SERVICES = [ + { + num: "01", + title: "모니터링", + desc: "시스템 및 네트워크 상태를 24/7 실시간 모니터링", + img: "./images/mt_icon01.png", + }, + { + num: "02", + title: "장애 대응", + desc: "이상 감지 시 전문 인력이 신속하게 원인 분석 및 복구", + img: "./images/mt_icon02.png", + }, + { + num: "03", + title: "보안 관리", + desc: "취약점 점검 및 패치 관리로 안전한 시스템 운영", + img: "./images/mt_icon03.png", + }, + { + num: "04", + title: "기술 지원", + desc: "운영 가이드, 문의 응대 및 기술 지원 제공", + img: "./images/mt_icon04.png", + }, + { + num: "05", + title: "지속적 개선", + desc: "정기 리포트 및 분석을 통한 지속적인 서비스 개선", + img: "./images/mt_icon05.png", + }, +]; + +const KPI = [ + { value: 99.9, suffix: "%", label: "서비스 가용성", icon: "⏱" }, + { value: 24, suffix: "/7", label: "365일 실시간 운영", icon: "📡" }, + { value: 10, suffix: "m 24s", label: "평균 응답 시간", icon: "⚡" }, + { value: 100, suffix: "%", label: "SLA 준수율", icon: "✓" }, +]; + +function CountUp({ target, suffix, inView }) { + const [display, setDisplay] = useState(0); + useEffect(() => { + if (!inView) return; + const controls = animate(0, target, { + duration: 1.8, + ease: "easeOut", + onUpdate: (v) => setDisplay(Math.round(v * 10) / 10), + }); + return controls.stop; + }, [inView, target]); + return ( + + {display} + {suffix} + + ); +} function MaintenancePage() { const ref = useFadeIn(); const introRef = useRef(null); - const introInView = useInView(introRef, { once: true, margin: "-60px" }); - const ease = [0.22, 1, 0.36, 1]; - const BUSINESS_NAV = [ - { label: "System Integration", to: "/business/si" }, - { label: "R&D", to: "/business/rnd" }, - { label: "운영 · 유지보수", to: "/business/maintenance" }, - ]; + const kpiRef = useRef(null); + const servicesRef = useRef(null); + const introInView = useInView(introRef, { once: true, margin: "-80px" }); + const kpiInView = useInView(kpiRef, { once: true, margin: "-80px" }); + const servicesInView = useInView(servicesRef, { once: true, margin: "-60px" }); + const [activeIdx, setActiveIdx] = useState(0); + return (
- {/* 안정적인 시스템 관리 -
*/} Maintenance } - // desc="구축 이후에도 끊김 없는 서비스 운영을 위해 장기 파트너십 기반의 유지보수를 제공합니다." navItems={BUSINESS_NAV} />
- {/* 개요 인트로 */} -
-
- - Overview + {/* ── 인트로 섹션 ── */} +
+ {/* 좌측 */} +
+ + OUR SERVICE - - 운영부터 개선까지 + +
+ {["운영부터 개선까지", "전문적인 관리 서비스"].map((line, i) => ( +
+ + {line} + +
+ ))} +
+ + + 전문 엔지니어가 시스템 전반을 관리하고,
- 전문적인 관리 서비스 -
+ 문제 발생 시 신속하게 대응하여 서비스 안정성을 유지합니다. + + + + 서비스 자세히 보기 + + + + + + {/* quote 카드 */} + +
"
+

+ 안정적인 운영은 +
+ 지속 가능한 성장의 +
+ 기반입니다. +

+ PAL Networks +
+
+ + {/* 우측 서비스 리스트 */} +
+
    + {SERVICES.map((svc, i) => ( + setActiveIdx(i)}> + {svc.num} +
    + {svc.title} + {svc.desc} +
    +
    + {svc.title} +
    +
    + + ))} +
+
+
+
+ + {/* ── KPI 바 ── */} +
+
+
+ {KPI.map((k, i) => ( + + {k.icon} + + + + {k.label} + + ))} +
+
+
+ + {/* ── 5컬럼 서비스 ── */} +
+
+ + SERVICE DETAIL + +
+ {SERVICES.map((svc, i) => ( + +
+ {svc.title} +
+ {svc.num} +

{svc.title}

+

{svc.desc}

+
+ + ))}