diff --git a/public/images/main_utm_img.png b/public/images/main_utm_img.png new file mode 100644 index 0000000..8c5bd6e Binary files /dev/null and b/public/images/main_utm_img.png differ diff --git a/src/components/main/MainUtm.jsx b/src/components/main/MainUtm.jsx index 7518f78..41788c4 100644 --- a/src/components/main/MainUtm.jsx +++ b/src/components/main/MainUtm.jsx @@ -1,200 +1,359 @@ -import { useEffect, useRef } from "react"; -import { gsap } from "gsap"; -import { ScrollTrigger } from "gsap/ScrollTrigger"; +import { useRef, useEffect, useState } from "react"; +import { motion, useInView, AnimatePresence } from "framer-motion"; +import utmMapImg from "../../../public/images/main_utm_img.png"; + +const ease = [0.22, 1, 0.36, 1]; + +const FEATURES = [ + { num: "01", label: "비행 계획" }, + { num: "02", label: "비행 승인" }, + { num: "03", label: "실시간 관제" }, + { num: "04", label: "데이터 관리" }, +]; + +const FLIGHT_PLANS = [ + { id: "FP-001", pilot: "홍길동", route: "서울 → 김포", status: "대기" }, + { id: "FP-002", pilot: "김철수", route: "인천 → 수원", status: "대기" }, + { id: "FP-003", pilot: "이영희", route: "김포 → 부천", status: "승인" }, +]; + +const DETAIL = { + id: "FP-001", + pilot: "홍길동", + pilotId: "hong001", + route: "서울 → 김포", + altitude: "100m", + speed: "13m/s", + date: "2025-06-10 14:30", +}; + +const PHASES = ["list", "detail", "confirm", "done"]; +const PHASE_DURATION = { list: 1800, detail: 2200, confirm: 1800, done: 2000 }; + +function UtmSystemPanel({ phase, activeRow }) { + return ( +
+
+ 비행계획 승인관리 + + 검색결과 총 {FLIGHT_PLANS.length}건 + +
+ +
+
+ 계획 ID + 신청자 + 경로 + 상태 + +
+ {FLIGHT_PLANS.map((row, i) => ( +
+ {row.id} + {row.pilot} + {row.route} + + {row.status} + + + + 상세보기 + + +
+ ))} +
-gsap.registerPlugin(ScrollTrigger); + {/* 상세: 아래로 펼쳐짐 */} +
+
비행계획 상세
+
+
+ 계획 ID + {DETAIL.id} +
+
+ 신청자 + + {DETAIL.pilot} ({DETAIL.pilotId}) + +
+
+ 경로 + {DETAIL.route} +
+
+ 고도 + + {DETAIL.altitude} · {DETAIL.speed} + +
+
+ 신청일시 + {DETAIL.date} +
+
+ 상태 + + {phase === "done" ? "승인" : "대기"} + +
+
+ + {phase === "detail" && ( +
+ + 승인처리 + +
+ )} + + + {phase === "done" && ( + + + FP-001 승인이 완료되었습니다. + + )} + +
+ + {/* 컨펌: 패널 안에서 블러 오버레이 */} + + {phase === "confirm" && ( + + +
⚠️
+
+ 비행계획을 승인하시겠습니까? +
+
+ FP-001 · 홍길동 · 서울 → 김포 +
+
+ 취소 + 확인 +
+
+
+ )} +
+
+ ); +} function MainUtm() { - const sectionRef = useRef(null); - const cardsRef = useRef([]); - - const items = [ - { - step: "01", - label: "비행 검토", - title: "비행가능여부 확인", - desc: "선택한 공역에서 드론 비행 가능 여부와 제한 조건을 실시간으로 확인합니다.", - }, - { - step: "02", - label: "승인 신청", - title: "자동비행승인 신청", - desc: "복잡한 승인 절차 없이 간편하게 비행 자동 승인을 신청할 수 있습니다.", - }, - { - step: "03", - label: "비행 관제", - title: "실시간 모니터링", - desc: "드론의 위치, 비행 경로, 운항 상태를 실시간으로 확인하고 모니터링합니다.", - }, - { - step: "04", - label: "통합 관리", - title: "비행 데이터 관리", - desc: "비행 이력과 운항 스케줄 데이터를 통합 관리하여 효율적인 드론 운영을 지원합니다.", - }, - ]; + const ref = useRef(null); + const inView = useInView(ref, { once: false, margin: "-80px" }); + const [phase, setPhase] = useState("list"); + const [activeRow] = useState(0); + const cursorRef = useRef(null); useEffect(() => { - const ctx = gsap.context(() => { - const cards = cardsRef.current.filter(Boolean); - - gsap.set(cards, { - yPercent: 110, - scale: 1, - opacity: 1, - rotateX: 0, - transformOrigin: "center bottom", + if (!inView) return; + let t; + const run = (current) => { + const next = PHASES[(PHASES.indexOf(current) + 1) % PHASES.length]; + t = setTimeout(() => { + setPhase(next); + run(next); + }, PHASE_DURATION[current]); + }; + t = setTimeout(() => run("list"), 1000); + return () => clearTimeout(t); + }, [inView]); + + // 커서 이동 로직 + useEffect(() => { + if (!inView) return; + + const showcase = ref.current?.querySelector(".utm-hero__showcase"); + const cursor = cursorRef.current; + if (!showcase || !cursor) return; + + let timers = []; + + function getPos(selector) { + const el = ref.current?.querySelector(selector); + if (!el) return null; + const sr = showcase.getBoundingClientRect(); + const er = el.getBoundingClientRect(); + return { + x: er.left - sr.left + er.width / 2, + y: er.top - sr.top + er.height / 2, + }; + } + + function moveTo(x, y) { + cursor.style.transform = `translate(${x}px, ${y}px)`; + } + + function click() { + cursor.classList.add("utm-cursor--click"); + setTimeout(() => cursor.classList.remove("utm-cursor--click"), 250); + } + + function after(ms, fn) { + const t = setTimeout(fn, ms); + timers.push(t); + } + + function loop() { + timers.forEach(clearTimeout); + timers = []; + + setPhase("list"); + after(1000, () => { + const p = getPos(".utm-panel__row--active .utm-panel__btn"); + if (p) moveTo(p.x, p.y); }); - gsap.set(cards[0], { - yPercent: 0, + after(2000, () => { + click(); + after(200, () => setPhase("detail")); }); - const tl = gsap.timeline({ - scrollTrigger: { - trigger: sectionRef.current, - start: "top top", - end: `+=${items.length * 900}`, - scrub: 1, - pin: true, - anticipatePin: 1, - }, + after(3200, () => { + const p = getPos(".utm-panel__approve-btn"); + if (p) moveTo(p.x, p.y); }); - cards.forEach((card, index) => { - if (index === 0) return; - - const prevCard = cards[index - 1]; - - tl.to( - prevCard, - { - yPercent: -18, - scale: 0.88, - opacity: 0.35, - rotateX: 8, - filter: "blur(3px)", - duration: 1, - ease: "none", - }, - index - 0.85, - ); - - tl.to( - card, - { - yPercent: 0, - duration: 1, - ease: "none", - }, - index - 0.85, - ); + after(4200, () => { + click(); + after(200, () => setPhase("confirm")); }); - tl.to(cards[cards.length - 1], { - yPercent: -10, - scale: 0.94, - duration: 0.8, - ease: "none", + after(5000, () => { + const p = getPos(".utm-confirm__ok"); + if (p) moveTo(p.x, p.y); }); - }, sectionRef); - - return () => ctx.revert(); - }, [items.length]); - - return ( -
-
-
- - - -
-
-

UTM SYSTEM

+ after(5800, () => { + click(); + after(200, () => setPhase("done")); + }); -

드론교통관리 (UTM)

+ after(7500, () => loop()); + } -

드론 하늘길을 통제하는 관제 시스템

-
+ moveTo(180, 160); + after(500, () => loop()); -
- {items.map((item, index) => ( -
{ - cardsRef.current[index] = el; - }} - > -
- {item.step} -

{item.label}

-

{item.title}

-

{item.desc}

-
- -
-
- -
-
-
+ return () => { + timers.forEach(clearTimeout); + timers = []; + cursor.classList.remove("utm-cursor--click"); + setPhase("list"); // ← cleanup에서만 호출 + }; + }, [inView]); + return ( +
+
+
+ +
+ + UTM / UATM PLATFORM + + + + 드론 비행의 모든 과정을 +
+ 하나의 플랫폼에서 +
+ + + 비행 계획부터 승인, 실시간 관제, 데이터 관리까지 +
더 안전하고 효율적인 하늘길을 만듭니다. +
+ + + {FEATURES.map((f) => ( +
  • + {f.num} + {f.label} +
  • ))} -
    + + + +
    + UTM 관제 지도 +
    + + + + {/* 커서 */} +
    +
    +
    +
    ); diff --git a/src/css/main.css b/src/css/main.css index 6367104..5dd7a62 100644 --- a/src/css/main.css +++ b/src/css/main.css @@ -115,115 +115,191 @@ body{overflow-x:hidden;} .main-scroll-text{font-size:10px;letter-spacing:.22em;} } -/* ─── utm ─── */ -.main-utm-section{position:relative;width:100%;min-height:100vh;padding-top:86px;overflow:hidden;background:radial-gradient(circle at 12% 18%,rgba(26,31,94,.08),transparent 32%),radial-gradient(circle at 88% 18%,rgba(26,31,94,.06),transparent 34%),linear-gradient(180deg,#f7f9ff 0%,#ffffff 100%);} -.main-utm-section::before{content:"";position:absolute;top:0;right:0;width:68%;height:58%;background:url("/images/main-utm-background.png") no-repeat center top/cover;opacity:.5;pointer-events:none;z-index:0;-webkit-mask-image:linear-gradient(180deg,#000 0%,#000 58%,rgba(0,0,0,.45) 78%,transparent 100%);mask-image:linear-gradient(180deg,#000 0%,#000 58%,rgba(0,0,0,.45) 78%,transparent 100%);} -.main-utm-section::after{content:"";position:absolute;inset:0;background:linear-gradient(90deg,rgba(247,249,255,.86) 0%,rgba(247,249,255,.42) 22%,rgba(247,249,255,.08) 52%,rgba(247,249,255,.42) 78%,rgba(247,249,255,.86) 100%);pointer-events:none;z-index:0;} - -.main-utm-bg-glow{position:absolute;border-radius:999px;filter:blur(90px);pointer-events:none;} -.main-utm-bg-glow--a{width:520px;height:520px;top:-160px;right:-120px;background:rgba(26,31,94,.13);} -.main-utm-bg-glow--b{width:460px;height:460px;left:-140px;bottom:-160px;background:rgba(112,180,255,.12);} - -.main-utm-inner{position:relative;z-index:2;width:min(1660px,calc(100% - 120px));min-height:calc(100vh - 86px);margin:0 auto;padding-top:72px;padding-bottom:64px;} - -.main-utm-head{position:relative;z-index:5;max-width:820px;margin-bottom:64px;} -.main-utm-eyebrow{margin:0 0 14px;font-size:12px;font-weight:800;letter-spacing:.24em;color:#1a1f5e;} -.main-utm-title{margin:0;font-size:clamp(40px,4vw,64px);font-weight:800;line-height:.92;letter-spacing:-0.08em;color:#0e1120;} -.main-utm-desc{margin:22px 0 0;font-size:16px;line-height:1.6;letter-spacing:-.02em;color:#697083;} - -.main-utm-stack{position:relative;width:100%;height:min(430px,50vh);perspective:1400px;} -.main-utm-card{position:absolute;inset:0;display:grid;grid-template-columns:.9fr 1.1fr;align-items:center;gap:64px;padding:54px 62px;border-radius:34px;overflow:hidden;background:rgba(255,255,255,.86);border:1px solid rgba(26,31,94,.1);box-shadow:0 30px 80px rgba(14,17,32,.1),inset 0 1px 0 rgba(255,255,255,.9);backdrop-filter:blur(22px);will-change:transform,opacity,filter;} -.main-utm-card::before{content:"";position:absolute;inset:0;background:linear-gradient(135deg,rgba(255,255,255,.78),transparent 46%),radial-gradient(circle at 82% 28%,rgba(26,31,94,.11),transparent 34%);pointer-events:none;} -.main-utm-card-text,.main-utm-card-visual{position:relative;z-index:2;} -.main-utm-step{display:inline-flex;align-items:center;justify-content:center;width:58px;height:32px;margin-bottom:24px;border-radius:999px;background:rgba(26,31,94,.1);color:#1a1f5e;font-size:13px;font-weight:800;letter-spacing:.1em;} -.main-utm-label{margin:0 0 10px;font-size:12px;font-weight:800;letter-spacing:.18em;color:rgba(26,31,94,.62);} -.main-utm-card h3{margin:0;font-size:clamp(34px,3.2vw,54px);line-height:1.06;letter-spacing:-.055em;color:#101322;} -.main-utm-card-text>p:last-child{max-width:430px;margin:22px 0 0;font-size:17px;line-height:1.72;word-break:keep-all;color:#636b7e;} - -.main-utm-card-visual{position:relative;height:100%;min-height:300px;border-radius:28px;overflow:hidden;background:#f7f8fc;align-items:center;overflow:hidden;justify-content:center;} -.main-utm-card-visual::after{content:"";position:absolute;inset:18px;border-radius:24px;background:linear-gradient(180deg,rgba(255,255,255,.12),transparent 30%);pointer-events:none;} -.main-utm-img{width:100%;height:100%;object-fit:cover;display:block;border-radius:24px;box-shadow:inset 0 0 0 1px rgba(26,31,94,.06),0 18px 40px rgba(17,22,40,.08),0 0 0 8px rgba(255,255,255,.42);background:#fff;overflow:hidden;transform:translateZ(0);} -.main-utm-orbit{position:absolute;inset:32px;border-radius:28px;} -.main-utm-orbit span{position:absolute;border:1px solid rgba(26,31,94,.14);border-radius:50%;} -.main-utm-orbit span:nth-child(1){width:340px;height:340px;left:50%;top:50%;transform:translate(-50%,-50%);} -.main-utm-orbit span:nth-child(2){width:230px;height:230px;left:18%;top:16%;} -.main-utm-orbit span:nth-child(3){width:170px;height:170px;right:10%;bottom:10%;} -.main-utm-map{position:absolute;inset:0;} -.main-utm-route{position:absolute;height:2px;border-radius:999px;background:linear-gradient(90deg,transparent,#1a1f5e,transparent);box-shadow:0 0 16px rgba(26,31,94,.32);opacity:.7;} -.main-utm-route--a{width:62%;left:18%;top:42%;transform:rotate(-18deg);} -.main-utm-route--b{width:48%;right:12%;top:62%;transform:rotate(22deg);} - -.utm-floating-air{position:absolute;top:120px;right:2%;width:42vw;height:210px;pointer-events:none;z-index:1;overflow:visible;opacity:.78;} -.utm-floating-drone{position:absolute;width:46px;height:46px;border-radius:18px;background:rgba(255,255,255,.52);border:1px solid rgba(26,31,94,.1);backdrop-filter:blur(12px);box-shadow:0 14px 30px rgba(31,41,55,.08);} -.utm-floating-drone::before{content:"";position:absolute;inset:-10px;border-radius:24px;border:1px solid rgba(91,108,255,.08);opacity:.6;animation:utmPulse 4s ease-out infinite;} -.utm-floating-drone svg{position:absolute;inset:10px;width:26px;height:26px;overflow:visible;} -.utm-floating-drone svg circle{fill:none;stroke:#1a1f5e;stroke-width:1.7;opacity:.72;} -.utm-floating-drone svg path{fill:none;stroke:#1a1f5e;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;opacity:.72;} -.utm-floating-drone span{display:none;} -.utm-floating-drone--a{left:10%;top:122px;animation:utmDroneMoveA 9s ease-in-out infinite;} -.utm-floating-drone--b{left:44%;top:72px;animation:utmDroneMoveB 11s ease-in-out infinite;animation-delay:-2s;} -.utm-floating-drone--c{right:4%;top:138px;animation:utmDroneMoveC 10s ease-in-out infinite;animation-delay:-4s;} -.utm-floating-drone--a svg circle,.utm-floating-drone--a svg path{stroke:#5B6CFF;} -.utm-floating-drone--b svg circle,.utm-floating-drone--b svg path{stroke:#8F1700;} -.utm-floating-drone--c svg circle,.utm-floating-drone--c svg path{stroke:#4F7DF3;} -.utm-floating-drone--a svg circle,.utm-floating-drone--a svg path{stroke:#5B6CFF;} -.utm-floating-drone--b svg circle,.utm-floating-drone--b svg path{stroke:#8F1700;} -.utm-floating-drone--c svg circle,.utm-floating-drone--c svg path{stroke:#4F7DF3;} - -@keyframes utmDroneMoveA{ -0%{transform:translate3d(0,0,0) rotate(-6deg);} -25%{transform:translate3d(12px,-10px,0) rotate(-2deg);} -50%{transform:translate3d(-6px,-18px,0) rotate(2deg);} -75%{transform:translate3d(-14px,-6px,0) rotate(-4deg);} -100%{transform:translate3d(0,0,0) rotate(-6deg);} +/* UTM */ +.utm-hero { position: relative; overflow: hidden; background: linear-gradient(180deg, #f0f4ff 0%, #f7f9ff 60%, #ffffff 100%); min-height: 100vh; display: flex; align-items: center; padding: 80px 0; } + +.utm-hero__blob { position: absolute; border-radius: 50%; pointer-events: none; filter: blur(72px); } + +.utm-hero__blob--1 { width: 480px; height: 480px; top: -120px; left: -80px; background: rgba(99,102,241,0.07); } + +.utm-hero__blob--2 { width: 360px; height: 360px; bottom: -80px; right: 10%; background: rgba(139,92,246,0.06); } + +.utm-hero__inner { max-width: 1200px; margin: 0 auto; padding: 0 40px; display: flex; flex-direction: column; align-items: center; text-align: center; position: relative; z-index: 1; width: 100%; } + +.utm-hero__eyebrow { display: inline-block; font-size: 11px; font-weight: 700; letter-spacing: 2.5px; text-transform: uppercase; color: #6366F1; margin-bottom: 24px; } + +.utm-hero__title { font-size: clamp(36px, 4.5vw, 64px); font-weight: 800; line-height: 1.15; letter-spacing: -0.03em; color: #0e1120; margin: 0 0 24px; word-break: keep-all; } + +.utm-hero__title em { font-style: normal; color: #1A1F5E; -webkit-text-fill-color: #1A1F5E; } + +.utm-hero__desc { font-size: 16px; color: #666; line-height: 1.85; margin: 0 0 36px; word-break: keep-all; } + +.utm-hero__chips { list-style: none; display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; margin: 0 0 48px; padding: 0; } + +.utm-hero__chip { display: flex; align-items: center; gap: 8px; background: rgba(255,255,255,0.75); border: 1px solid rgba(99,102,241,0.18); border-radius: 999px; padding: 7px 16px 7px 10px; backdrop-filter: blur(8px); } + +.utm-hero__chip-num { font-size: 10px; font-weight: 700; color: #6366F1; letter-spacing: 0.5px; } + +.utm-hero__chip-label { font-size: 13px; font-weight: 600; color: #1A1F5E; } + +.utm-hero__showcase { + position: relative; + width: 100%; + border-radius: 20px; + overflow: visible; /* ← 핵심: 패널이 밖으로 나올 수 있게 */ + box-shadow: 0 32px 80px rgba(26,31,94,0.16), 0 8px 24px rgba(26,31,94,0.08); } -@keyframes utmDroneMoveB{ -0%{transform:translate3d(0,0,0) rotate(5deg);} -25%{transform:translate3d(-10px,8px,0) rotate(1deg);} -50%{transform:translate3d(14px,-12px,0) rotate(-3deg);} -75%{transform:translate3d(6px,10px,0) rotate(3deg);} -100%{transform:translate3d(0,0,0) rotate(5deg);} +/* 지도 full width */ +.utm-hero__map-wrap { + position: relative; + width: 100%; + border-radius: 20px; + overflow: hidden; +} + +.utm-hero__map-img { + display: block; + width: 100%; + height: 100%; + object-fit: cover; +} + +.utm-panel { + position: absolute; + bottom: -32px; + left: -140px; + width: 340px; + background: #1a1d2e; + padding: 24px 20px; + display: flex; + flex-direction: column; + gap: 0; + border-radius: 16px; + overflow: hidden; + box-shadow: 0 24px 60px rgba(0,0,0,0.45), 0 0 0 1px rgba(99,102,241,0.2); + z-index: 5; +} + +.utm-panel__header { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; } + +.utm-panel__title { font-size: 14px; font-weight: 700; color: #fff; } + +.utm-panel__badge { font-size: 11px; font-weight: 600; background: rgba(249,115,22,0.2); color: #f97316; border-radius: 4px; padding: 2px 8px; } + +.utm-panel__table { display: flex; flex-direction: column; border: 1px solid rgba(255,255,255,0.07); border-radius: 10px; overflow: hidden; } + +.utm-panel__thead { display: grid; grid-template-columns: 1.1fr 0.8fr 1.2fr 0.7fr 1fr; padding: 8px 12px; background: rgba(255,255,255,0.05); font-size: 11px; color: rgba(255,255,255,0.4); font-weight: 600; } + +.utm-panel__row { display: grid; grid-template-columns: 1.1fr 0.8fr 1.2fr 0.7fr 1fr; padding: 10px 12px; border-top: 1px solid rgba(255,255,255,0.05); align-items: center; transition: background 0.2s; } + +.utm-panel__row--active { background: rgba(99,102,241,0.1); } + +.utm-panel__cell { font-size: 12px; color: rgba(255,255,255,0.75); } + +.utm-panel__status { font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 4px; display: inline-block; } + +.utm-panel__status--wait { background: rgba(251,191,36,0.15); color: #fbbf24; } + +.utm-panel__status--done { background: rgba(52,211,153,0.15); color: #34d399; } + +.utm-panel__btn { font-size: 11px; margin-left: 8px; font-weight: 600; background: #6366F1; color: #fff; border-radius: 5px; padding: 4px 10px; display: inline-block; } + +.utm-panel__btn--hover { background: #4f46e5; box-shadow: 0 0 0 3px rgba(99,102,241,0.3); } + +/* 상세박스: 아래로 펼쳐지는 애니메이션 */ +.utm-panel__detail { + background: rgba(255,255,255,0.04); + border: 1px solid rgba(255,255,255,0.08); + border-radius: 10px; + padding: 0 16px; + max-height: 0; + overflow: hidden; + transition: max-height 0.5s cubic-bezier(0.22, 1, 0.36, 1), + padding 0.3s ease, + margin-top 0.3s ease; + margin-top: 0; } -@keyframes utmDroneMoveC{ -0%{transform:translate3d(0,0,0) rotate(-4deg);} -25%{transform:translate3d(8px,-14px,0) rotate(0deg);} -50%{transform:translate3d(-12px,-4px,0) rotate(4deg);} -75%{transform:translate3d(10px,12px,0) rotate(-2deg);} -100%{transform:translate3d(0,0,0) rotate(-4deg);} +.utm-panel__detail--show { + max-height: 400px; + padding: 14px 16px; + margin-top: 16px; } -@keyframes utmPulse{ -0%{transform:scale(.9);opacity:.4;} -70%{opacity:0;} -100%{transform:scale(1.35);opacity:0;} +.utm-panel__detail-title { font-size: 13px; font-weight: 700; color: #fff; margin-bottom: 2px; } + +.utm-panel__detail-rows { display: flex; flex-direction: column; gap: 6px; } + +.utm-panel__detail-row { display: flex; justify-content: space-between; align-items: center; font-size: 12px; } + +.utm-panel__detail-row span:first-child { color: rgba(255,255,255,0.4); } + +.utm-panel__detail-row span:last-child { color: rgba(255,255,255,0.85); font-weight: 500; } + +.utm-panel__detail-actions { display: flex; justify-content: flex-end; margin-top: 14px; } + +.utm-panel__approve-btn { font-size: 12px; font-weight: 700; background: #6366F1; color: #fff; border-radius: 6px; padding: 7px 16px; display: inline-block; } + +.utm-panel__approve-btn--hover { background: #4f46e5; box-shadow: 0 0 0 3px rgba(99,102,241,0.35); } + +.utm-panel__toast { display: flex; align-items: center; gap: 8px; background: rgba(52,211,153,0.15); border: 1px solid rgba(52,211,153,0.3); border-radius: 8px; padding: 10px 14px; font-size: 12px; font-weight: 600; color: #34d399; margin-top: 4px; } + +.utm-panel__toast-icon { font-size: 14px; font-weight: 800; } +.utm-panel__confirm-overlay { + position: absolute; + inset: 0; + background: rgba(10, 10, 30, 0.6); + backdrop-filter: blur(6px); + display: flex; + align-items: center; + justify-content: center; + z-index: 20; + border-radius: 16px; } +.utm-confirm { background: #22253a; border: 1px solid rgba(255,255,255,0.12); border-radius: 16px; padding: 28px 24px; display: flex; flex-direction: column; align-items: center; gap: 12px; width: 260px; text-align: center; box-shadow: 0 32px 80px rgba(0,0,0,0.5), 0 0 0 1px rgba(99,102,241,0.2); gap: 14px;} + +.utm-confirm__icon { font-size: 32px; } + +.utm-confirm__title { font-size: 16px; font-weight: 700; color: #fff; line-height: 1.4; } + +.utm-confirm__desc { font-size: 13px; color: rgba(255,255,255,0.5); } -/* ─── Responsive ─── */ -@media(max-width:1024px){.main-utm-section{padding-top:76px;} -.main-utm-inner{width:calc(100% - 56px);min-height:calc(100vh - 76px);padding-top:56px;} -.main-utm-head{margin-bottom:56px;} -.main-utm-card{grid-template-columns:1fr;gap:28px;padding:34px;} -.main-utm-card-visual{min-height:240px;} -.utm-floating-air{width:58vw;top:160px;opacity:.72;} +.utm-confirm__btns { display: flex; gap: 10px; margin-top: 8px; width: 100%; } + +.utm-confirm__cancel { flex: 1; text-align: center; font-size: 14px; font-weight: 600; padding: 11px; border-radius: 10px; background: rgba(255,255,255,0.08); color: rgba(255,255,255,0.6); } + +.utm-confirm__ok { flex: 1; text-align: center; font-size: 14px; font-weight: 700; padding: 11px; border-radius: 10px; background: #6366F1; color: #fff; box-shadow: 0 4px 16px rgba(99,102,241,0.4); } + +.utm-cursor { + position: absolute; + top: 0; + left: 0; + pointer-events: none; + z-index: 100; + transition: transform 0.7s cubic-bezier(0.22, 1, 0.36, 1); } -@media(max-width:768px){.main-utm-inner{width:calc(100% - 32px);padding-top:42px;} -.main-utm-title{font-size:38px;} -.main-utm-desc{font-size:14px;} -.main-utm-stack{height:64vh;} -.main-utm-card{padding:26px 22px;border-radius:24px;} -.main-utm-card h3{font-size:32px;} -.main-utm-card-text>p:last-child{font-size:14px;} -.main-utm-card-visual{min-height:210px;} -.utm-floating-air{display:none;} +.utm-cursor__dot { + width: 20px; + height: 20px; + background: #fff; + border: 2px solid #6366F1; + border-radius: 50%; + box-shadow: 0 2px 10px rgba(99, 102, 241, 0.45); + transition: transform 0.15s ease; } -/* ─── Keyframes ─── */ +.utm-cursor--click .utm-cursor__dot { + transform: scale(0.65); +} + +@media (max-width: 1024px) { .utm-hero__showcase { grid-template-columns: 1fr; } .utm-hero__map-wrap { height: 280px; } } + +@media (max-width: 768px) { .utm-hero { padding: 72px 0 60px; } .utm-hero__inner { padding: 0 20px; } .utm-hero__title { font-size: clamp(28px, 7vw, 42px); } .utm-hero__desc { font-size: 14px; } .utm-hero__chips { gap: 8px; margin-bottom: 36px; } .utm-hero__map-wrap { height: 220px; } .utm-panel { padding: 16px 14px; min-height: auto; } } -@keyframes utmWaveMove{0%{transform:translateX(-120%);}100%{transform:translateX(120%);}} +@media (max-width: 480px) { .utm-hero__inner { padding: 0 16px; } .utm-hero__chip { padding: 6px 12px 6px 8px; } .utm-hero__chip-label { font-size: 12px; } } -/* ─── UTM ─── */ +/* ─── UAM ─── */ .aurora-canvas {position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 0; }