"use client"; import React, { useEffect, useRef, useState } from "react"; import dynamic from "next/dynamic"; import { motion, AnimatePresence, useMotionValue, useTransform } from "framer-motion"; import gsap from "gsap"; import { ScrollTrigger } from "gsap/ScrollTrigger"; import Lenis from "lenis"; import { COLORS, PHASE_LABELS, PhaseKey, phaseFromProgress, rgba, } from "./constants"; import MetricsPanel from "./MetricsPanel"; // 3D scene is client-only and code-split so it never blocks first paint. const OptimizationCanvas = dynamic(() => import("./OptimizationCanvas"), { ssr: false, }); const PHASE_ORDER: PhaseKey[] = [ "chaos", "scan", "dissolve", "optimize", "reorganize", "metrics", ]; const WORKFLOW_STEPS = [ { label: "Analyze", icon: "🔍", activateAt: 0 }, { label: "Optimize", icon: "⚡", activateAt: 2 }, { label: "Assign", icon: "🚛", activateAt: 3 }, { label: "Execute", icon: "📡", activateAt: 4 }, { label: "Monitor", icon: "📊", activateAt: 5 }, ]; export default function OptimizationSection() { const containerRef = useRef(null); const progressRef = useRef(0); const scroll = useMotionValue(0); const [phase, setPhase] = useState("chaos"); const [pinState, setPinState] = useState<"before" | "pinned" | "after">("before"); const [mountScene, setMountScene] = useState(false); const [sceneActive, setSceneActive] = useState(false); const [isMobile, setIsMobile] = useState(false); const [reduced, setReduced] = useState(false); const [orders, setOrders] = useState(59); const [accuracy, setAccuracy] = useState(98.7); const [activeVehicles, setActiveVehicles] = useState(5); const [carbon, setCarbon] = useState(-12.0); const [routeHealth, setRouteHealth] = useState(99.4); // Interval timers for high-fidelity live dashboard fluctuations useEffect(() => { const ordersInterval = setInterval(() => { setOrders((prev) => prev + (Math.random() > 0.4 ? 1 : 0)); }, 4500); const accuracyInterval = setInterval(() => { setAccuracy((prev) => { const delta = (Math.random() - 0.5) * 0.15; const next = prev + delta; return parseFloat(Math.min(99.1, Math.max(98.4, next)).toFixed(2)); }); }, 2800); const vehicleInterval = setInterval(() => { setActiveVehicles((prev) => (prev === 5 ? (Math.random() > 0.5 ? 4 : 5) : (Math.random() > 0.3 ? 5 : 4))); }, 3500); const carbonInterval = setInterval(() => { setCarbon((prev) => { const delta = (Math.random() - 0.5) * 0.2; const next = prev + delta; return parseFloat(Math.min(-11.5, Math.max(-12.8, next)).toFixed(1)); }); }, 3200); const healthInterval = setInterval(() => { setRouteHealth((prev) => { const delta = (Math.random() - 0.5) * 0.12; const next = prev + delta; return parseFloat(Math.min(99.9, Math.max(98.8, next)).toFixed(2)); }); }, 2500); return () => { clearInterval(ordersInterval); clearInterval(accuracyInterval); clearInterval(vehicleInterval); clearInterval(carbonInterval); clearInterval(healthInterval); }; }, []); // Environment detection (client only). useEffect(() => { const mqMobile = window.matchMedia("(max-width: 767px)"); const mqReduce = window.matchMedia("(prefers-reduced-motion: reduce)"); const sync = () => { setIsMobile(mqMobile.matches); setReduced(mqReduce.matches); }; sync(); mqMobile.addEventListener("change", sync); mqReduce.addEventListener("change", sync); return () => { mqMobile.removeEventListener("change", sync); mqReduce.removeEventListener("change", sync); }; }, []); // Mount the WebGL scene when the section approaches the viewport, and pause // its render loop entirely once it scrolls off-screen (battery / 60fps). useEffect(() => { const el = containerRef.current; if (!el) return; const mountIo = new IntersectionObserver( (entries) => { if (entries.some((e) => e.isIntersecting)) { setMountScene(true); // Activate immediately on mount so the render loop starts even on a // direct scroll-jump (the activeIo below only fires on later changes). setSceneActive(true); mountIo.disconnect(); } }, { rootMargin: "120% 0px" }, ); const activeIo = new IntersectionObserver( (entries) => setSceneActive(entries.some((e) => e.isIntersecting)), { rootMargin: "10% 0px" }, ); mountIo.observe(el); activeIo.observe(el); return () => { mountIo.disconnect(); activeIo.disconnect(); }; }, []); // Drive the shared scroll progress with GSAP ScrollTrigger. // We pin via our own `position: fixed` (toggled by `pinState`) rather than // GSAP's pin or CSS `position: sticky`. CSS sticky is broken by an ancestor // (.body-container) using `overflow: hidden`, and GSAP's pin offsets the // element by the fixed site-header height. A self-managed fixed element // pins to the viewport top deterministically and ignores ancestor overflow. useEffect(() => { const el = containerRef.current; if (!el) return; gsap.registerPlugin(ScrollTrigger); // Smooth scroll (Lenis), driven by a SINGLE rAF source — GSAP's ticker. // Previously lenis.raf() was called from both a manual requestAnimationFrame // loop AND gsap.ticker, double-stepping the integrator every frame, which is // what made scrolling stutter. One source keeps Lenis + ScrollTrigger locked. const lenis = new Lenis({ duration: 1.05, easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)), orientation: "vertical", gestureOrientation: "vertical", smoothWheel: true, }); lenis.on("scroll", ScrollTrigger.update); const tickerCb = (time: number) => lenis.raf(time * 1000); // ticker is in seconds, Lenis wants ms gsap.ticker.add(tickerCb); gsap.ticker.lagSmoothing(0); let lastPhase: PhaseKey = "chaos"; let lastPin: "before" | "pinned" | "after" = "before"; const st = ScrollTrigger.create({ trigger: el, start: "top top", end: "bottom bottom", scrub: 0.4, invalidateOnRefresh: true, onUpdate: (self) => { const p = self.progress; progressRef.current = p; scroll.set(p); const next = phaseFromProgress(p); if (next !== lastPhase) { lastPhase = next; setPhase(next); } const ns = p <= 0.0002 ? "before" : p >= 0.9998 ? "after" : "pinned"; if (ns !== lastPin) { lastPin = ns; setPinState(ns); } }, }); const refresh = setTimeout(() => ScrollTrigger.refresh(), 300); return () => { clearTimeout(refresh); st.kill(); gsap.ticker.remove(tickerCb); lenis.destroy(); }; }, [scroll]); // Overlay reactions to scroll (no React re-render — direct DOM updates). const leftOpacity = useTransform(scroll, [0.3, 0.55], [1, 0.32]); const leftBlur = useTransform(scroll, [0.3, 0.55], [0, 3]); const leftFilter = useTransform(leftBlur, (b) => `blur(${b}px)`); const rightOpacity = useTransform(scroll, [0.42, 0.66], [0.36, 1]); const scanWidth = useTransform(scroll, [0, 1], ["0%", "100%"]); const scanLineY = useTransform(scroll, [0.2, 0.42], ["8%", "92%"]); const scanLineOpacity = useTransform(scroll, [0.18, 0.22, 0.42, 0.46], [0, 1, 1, 0]); const dividerOpacity = useTransform(scroll, [0.45, 0.6], [0.15, 0.75]); const phaseIndex = PHASE_ORDER.indexOf(phase); return (
{/* Static backdrop (also the canvas loading state) */}
{/* 3D scene */} {mountScene && (
)} {/* Depth vignette */}
{/* Floating AI Status Badge replacing giant abstract sphere centerpiece */} {phase !== "chaos" && (
{PHASE_LABELS[phase]}
)}
{/* Center scan divider */} {/* AI scan sweep line */} {/* UI overlay */}
{/* Header */}
Doormile AI Control Tower AI Logistics Optimization Engine Watch Doormile's AI engine transform chaotic logistics into precision-optimized delivery networks — reducing distance, fleet size, delays, and cost in real time. {/* Workflow step indicators */} {WORKFLOW_STEPS.map((step, i) => { const isActive = phaseIndex >= step.activateAt; const isCurrent = phaseIndex === step.activateAt; return ( {i > 0 && } {step.icon} {step.label} ); })} {/* Scan progress bar */}
{/* Side comparison panels */}
System: Congested

Without Optimization

  • Chaotic overlapping routes
  • Duplicate & idle trips
  • 8 vehicles required
  • 23 delivery delays
  • +18% cost overrun
System: Optimized

With Doormile AI

  • Optimized route clusters
  • Intelligent vehicle assignment
  • Multi-trip & EV planning
  • Zero delivery delays
  • 18% cost saved
  • Carbon footprint reduced
{/* KPI metrics */}
{/* Bottom insight bar */} Live Analytics: {orders} Orders AI Accuracy: {accuracy}% Fleet: {activeVehicles}/5 EV Active Route Health: {routeHealth}% Carbon: {carbon}%
); } const styles = ` /* ===== OUTER SECTION: Transparent so the card floats ===== */ .dm-opt { position: relative; height: 230vh; background: transparent; margin-bottom: 0; } .dm-opt-sticky { position: absolute; top: 0; left: 0; width: 100%; height: 100vh; overflow: hidden; background: transparent; } .dm-opt.is-pinned .dm-opt-sticky { position: fixed; top: 0; left: 0; } .dm-opt.is-after .dm-opt-sticky { position: absolute; top: auto; bottom: 0; } /* ===== FLOATING CARD — the only colored surface ===== */ .dm-opt-card { position: absolute !important; top: 110px !important; left: 40px !important; right: 40px !important; bottom: 0 !important; /* flat bottom + flush to container so the Performance card butts directly against it, reading as one continuous container (home-page technique) */ border-radius: 42px 42px 0 0 !important; overflow: hidden !important; // background: linear-gradient(165deg, #06101f 0%, #020617 35%, #040d1c 70%, #030a18 100%) !important; // border: 0px solid ${rgba("#ffffff", 0.08)} !important; border-bottom: none !important; // box-shadow: // 0 0 0 1px ${rgba(COLORS.cyan, 0.04)}, // 0 4px 30px -4px rgba(0, 0, 0, 0.7), // 0 20px 80px -20px rgba(0, 0, 0, 0.6), // 0 0 120px -30px ${rgba(COLORS.cyan, 0.08)}, // inset 0 1px 0 ${rgba("#ffffff", 0.06)}, // inset 0 -1px 0 ${rgba("#ffffff", 0.02)} !important; // box-sizing: border-box !important; } /* Animated subtle grid pattern */ .dm-opt-card::before { content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none; opacity: 0.035; background-image: linear-gradient(${rgba(COLORS.cyan, 0.5)} 1px, transparent 1px), linear-gradient(90deg, ${rgba(COLORS.cyan, 0.5)} 1px, transparent 1px); background-size: 60px 60px; animation: dmOptGridDrift 25s linear infinite; } @keyframes dmOptGridDrift { 0% { background-position: 0 0; } 100% { background-position: 60px 60px; } } /* Radial center glow behind 3D scene */ .dm-opt-card::after { content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none; background: radial-gradient(ellipse 50% 45% at 50% 48%, ${rgba(COLORS.cyan, 0.08)} 0%, transparent 70%), radial-gradient(ellipse 60% 40% at 50% 90%, ${rgba(COLORS.green, 0.05)} 0%, transparent 60%), radial-gradient(ellipse 80% 50% at 50% 10%, ${rgba(COLORS.cyan, 0.04)} 0%, transparent 50%); } @media (max-width: 1024px) { .dm-opt-card { top: 96px !important; left: 20px !important; right: 20px !important; bottom: 0 !important; border-radius: 42px 42px 0 0 !important; } } @media (max-width: 767px) { .dm-opt-card { top: 86px !important; left: 10px !important; right: 10px !important; bottom: 0 !important; border-radius: 28px 28px 0 0 !important; } } /* ===== INNER LAYERS ===== */ .dm-opt-backdrop { position: absolute; inset: 0; z-index: 0; background: radial-gradient(100% 70% at 50% 6%, ${rgba(COLORS.cyan, 0.06)} 0%, transparent 55%), radial-gradient(80% 60% at 50% 100%, ${rgba(COLORS.green, 0.05)} 0%, transparent 55%); } .dm-opt-canvas { position: absolute; inset: 0; z-index: 1; } .dm-opt-canvas canvas { display: block; } .dm-opt-vignette { position: absolute; inset: 0; z-index: 2; pointer-events: none; background: radial-gradient(110% 90% at 50% 50%, transparent 48%, ${rgba("#020617", 0.88)} 100%), linear-gradient(180deg, ${rgba("#020617", 0.6)} 0%, transparent 20%, transparent 65%, ${rgba("#020617", 0.92)} 100%); } .dm-opt-divider { position: absolute; left: 50%; top: 14%; bottom: 28%; width: 1px; z-index: 3; pointer-events: none; transform: translateX(-0.5px); background: linear-gradient(180deg, transparent, ${rgba(COLORS.cyan, 0.6)}, transparent); box-shadow: 0 0 16px ${rgba(COLORS.cyan, 0.4)}; } .dm-opt-scanline { position: absolute; left: 6%; right: 6%; height: 2px; z-index: 3; pointer-events: none; background: linear-gradient(90deg, transparent, ${COLORS.cyan}, transparent); box-shadow: 0 0 22px ${rgba(COLORS.cyan, 0.8)}; } /* ===== FLOATING AI STATUS BADGE ===== */ .dm-opt-floating-badge { pointer-events: none; } .dm-opt-floating-badge__inner { display: inline-flex; align-items: center; gap: 10px; padding: 8px 18px; border-radius: 999px; background: ${rgba(COLORS.ink, 0.85)}; border: 1.5px solid ${rgba(COLORS.cyan, 0.3)}; box-shadow: 0 10px 30px -5px rgba(0, 0, 0, 0.65), 0 0 24px -2px ${rgba(COLORS.cyan, 0.18)}, inset 0 1px 0 rgba(255, 255, 255, 0.08); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); transition: border-color 0.4s ease, box-shadow 0.4s ease; } .dm-opt-floating-badge__dot { width: 7px; height: 7px; border-radius: 50%; background: ${COLORS.cyan}; box-shadow: 0 0 10px ${COLORS.cyan}; animation: dmOptPulse 1.4s ease-in-out infinite; transition: background 0.4s ease, box-shadow 0.4s ease; } .dm-opt-floating-badge__dot.is-scan { background: ${COLORS.cyan}; box-shadow: 0 0 10px ${COLORS.cyan}; } .dm-opt-floating-badge__dot.is-dissolve, .dm-opt-floating-badge__dot.is-optimize { background: ${COLORS.amber}; box-shadow: 0 0 10px ${COLORS.amber}; } .dm-opt-floating-badge__dot.is-reorganize { background: #C084FC; box-shadow: 0 0 10px #C084FC; } .dm-opt-floating-badge__dot.is-metrics { background: ${COLORS.green}; box-shadow: 0 0 10px ${COLORS.green}; } .dm-opt-floating-badge__text { font-family: var(--font-space-grotesk), var(--font-manrope), system-ui, sans-serif; font-size: 10px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; color: #F8FAFC; text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5); } /* ===== UI OVERLAY ===== */ .dm-opt-ui { position: absolute; inset: 0; z-index: 4; pointer-events: none; } .dm-opt-ui h2, .dm-opt-ui h3, .dm-opt-metric__value, .dm-opt-eyebrow, .dm-opt-phase { font-family: var(--font-space-grotesk), var(--font-manrope), system-ui, sans-serif; } /* ===== HEADER — compact, no dead space ===== */ .dm-opt-head { position: absolute; top: clamp(18px, 3vh, 36px); left: 50%; transform: translateX(-50%); width: min(640px, 90vw); text-align: center; } .dm-opt-eyebrow { display: inline-flex; align-items: center; gap: 7px; font-size: 11px; letter-spacing: 0.22em; text-transform: uppercase; color: ${COLORS.cyan}; padding: 5px 14px; border-radius: 999px; background: ${rgba(COLORS.cyan, 0.06)}; border: 1px solid ${rgba(COLORS.cyan, 0.25)}; backdrop-filter: blur(8px); } .dm-opt-dot { width: 6px; height: 6px; border-radius: 50%; background: ${COLORS.cyan}; box-shadow: 0 0 10px ${COLORS.cyan}; } .dm-opt .dm-opt-head h2 { margin: 8px 0 4px !important; padding: 0 !important; color: #F8FAFC !important; font-weight: 700 !important; text-transform: none !important; font-size: clamp(22px, 2.4vw, 36px) !important; line-height: 1.1 !important; letter-spacing: -0.015em !important; } .dm-opt .dm-opt-head p { margin: 0 auto !important; padding: 0 !important; color: ${COLORS.textDim} !important; max-width: 440px; font-size: clamp(11px, 1vw, 13px) !important; line-height: 1.45 !important; } /* ===== WORKFLOW STEPS ===== */ .dm-opt-steps { display: flex; align-items: center; justify-content: center; gap: 0; margin-top: 12px; flex-wrap: wrap; } .dm-opt-steps__pill { display: inline-flex; align-items: center; gap: 4px; padding: 4px 10px; border-radius: 999px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: ${COLORS.slate}; background: ${rgba(COLORS.ink, 0.5)}; border: 1px solid ${rgba(COLORS.slate, 0.2)}; backdrop-filter: blur(6px); transition: all 0.45s cubic-bezier(0.22, 1, 0.36, 1); } .dm-opt-steps__pill.is-active { color: #E2E8F0; background: ${rgba(COLORS.cyan, 0.10)}; border-color: ${rgba(COLORS.cyan, 0.35)}; box-shadow: 0 0 18px -6px ${rgba(COLORS.cyan, 0.5)}; } .dm-opt-steps__pill.is-current { color: ${COLORS.cyan}; border-color: ${rgba(COLORS.cyan, 0.6)}; box-shadow: 0 0 24px -4px ${rgba(COLORS.cyan, 0.6)}; } .dm-opt-steps__icon { font-size: 11px; } .dm-opt-steps__text { font-size: 9.5px; } .dm-opt-steps__line { display: block; width: 16px; height: 1px; margin: 0 2px; background: ${rgba(COLORS.slate, 0.3)}; transition: background 0.45s ease; } .dm-opt-steps__line.is-active { background: linear-gradient(90deg, ${COLORS.cyan}, ${COLORS.green}); box-shadow: 0 0 6px ${rgba(COLORS.cyan, 0.5)}; } /* ===== PROGRESS BAR ===== */ .dm-opt-progress { margin-top: 10px; } .dm-opt-progress__track { height: 2px; border-radius: 999px; overflow: hidden; background: ${rgba(COLORS.cyan, 0.10)}; max-width: 420px; margin: 0 auto; } .dm-opt-progress__fill { height: 100%; border-radius: 999px; background: linear-gradient(90deg, ${COLORS.cyan}, ${COLORS.green}); box-shadow: 0 0 12px ${rgba(COLORS.cyan, 0.6)}; } .dm-opt-status { display: inline-flex; align-items: center; gap: 8px; margin-top: 8px; padding: 4px 11px; border-radius: 999px; background: ${rgba(COLORS.ink, 0.55)}; border: 1px solid ${rgba(COLORS.cyan, 0.18)}; backdrop-filter: blur(8px); } .dm-opt-status__dot { width: 5px; height: 5px; border-radius: 50%; background: ${COLORS.cyan}; box-shadow: 0 0 8px ${COLORS.cyan}; animation: dmOptPulse 1.4s ease-in-out infinite; } .dm-opt-status__label { font-size: 9.5px; letter-spacing: 0.14em; text-transform: uppercase; color: #E2E8F0; font-weight: 600; } .dm-opt-status__step { font-size: 9.5px; color: ${COLORS.cyan}; font-weight: 600; } /* ===== COMPARE PANELS — tighter, stronger ===== */ .dm-opt-compare { position: absolute; top: 50%; left: 0; right: 0; transform: translateY(-50%); display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 0 clamp(12px, 2.5vw, 36px); } .dm-opt-panel { pointer-events: auto; width: clamp(230px, 26vw, 340px); padding: 18px 20px; border-radius: 20px; background: ${rgba(COLORS.ink, 0.72)}; border: 1px solid ${rgba(COLORS.slate, 0.22)}; backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); } .dm-opt-panel--bad { border-color: ${rgba(COLORS.red, 0.45)}; box-shadow: 0 0 30px -8px ${rgba(COLORS.red, 0.35)}, 0 20px 50px -20px ${rgba(COLORS.red, 0.25)}, inset 0 1px 0 ${rgba(COLORS.red, 0.08)}; } .dm-opt-panel--good { border-color: ${rgba(COLORS.green, 0.45)}; box-shadow: 0 0 30px -8px ${rgba(COLORS.green, 0.35)}, 0 20px 50px -20px ${rgba(COLORS.green, 0.25)}, inset 0 1px 0 ${rgba(COLORS.green, 0.08)}; } .dm-opt .dm-opt-panel h3 { margin: 10px 0 12px !important; padding: 0 !important; color: #F1F5F9 !important; font-size: clamp(15px, 1.4vw, 19px) !important; font-weight: 600 !important; line-height: 1.15 !important; text-transform: none !important; letter-spacing: -0.01em !important; } .dm-opt .dm-opt-panel ul { list-style: none !important; margin: 0 !important; padding: 0 !important; display: grid; gap: 7px; } .dm-opt .dm-opt-panel li { position: relative; padding-left: 0 !important; margin: 0 !important; color: ${COLORS.textDim} !important; font-size: 12.5px !important; line-height: 1.35 !important; display: flex; align-items: center; gap: 8px; } .dm-opt .dm-opt-panel li::marker { content: "" !important; } /* Remove old dot pseudo — now using ✖/✔ markers */ .dm-opt .dm-opt-panel li::before { content: none !important; display: none !important; } /* ✖/✔ markers */ .dm-opt-marker { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 6px; flex-shrink: 0; font-size: 10px; font-weight: 700; line-height: 1; } .dm-opt-marker--x { background: ${rgba(COLORS.red, 0.15)}; color: ${COLORS.red}; border: 1px solid ${rgba(COLORS.red, 0.35)}; box-shadow: 0 0 8px ${rgba(COLORS.red, 0.3)}; } .dm-opt-marker--ok { background: ${rgba(COLORS.green, 0.15)}; color: ${COLORS.green}; border: 1px solid ${rgba(COLORS.green, 0.35)}; box-shadow: 0 0 8px ${rgba(COLORS.green, 0.3)}; } .dm-opt-panel__badge { display: inline-flex; align-items: center; gap: 7px; font-size: 10px; letter-spacing: 0.16em; text-transform: uppercase; font-weight: 700; color: ${COLORS.red}; padding: 5px 10px; border-radius: 999px; background: ${rgba(COLORS.red, 0.1)}; border: 1px solid ${rgba(COLORS.red, 0.35)}; } .dm-opt-panel__badge--good { color: ${COLORS.green}; background: ${rgba(COLORS.green, 0.1)}; border-color: ${rgba(COLORS.green, 0.35)}; } .dm-opt-pulse { width: 6px; height: 6px; border-radius: 50%; animation: dmOptPulse 1.4s ease-in-out infinite; } .dm-opt-pulse--red { background: ${COLORS.red}; box-shadow: 0 0 10px ${COLORS.red}; } .dm-opt-pulse--green { background: ${COLORS.green}; box-shadow: 0 0 10px ${COLORS.green}; } @keyframes dmOptPulse { 0%,100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.5); opacity: 0.5; } } /* ===== METRICS ===== */ .dm-opt-foot { position: absolute; left: 0; right: 0; bottom: clamp(12px, 2.5vh, 28px); padding: 0 clamp(12px, 3vw, 36px); } .dm-opt-metrics { pointer-events: auto; display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px; max-width: 1100px; margin: 0 auto; } .dm-opt-metric { position: relative; padding: 14px 14px 12px; border-radius: 16px; background: ${rgba(COLORS.ink, 0.72)}; border: 1px solid ${rgba(COLORS.slate, 0.25)}; backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); overflow: hidden; opacity: 0; transform: translateY(22px); animation: dmOptCardIn 0.6s cubic-bezier(0.22, 1, 0.36, 1) forwards; box-shadow: 0 8px 32px -8px rgba(0, 0, 0, 0.5), inset 0 1px 0 ${rgba("#ffffff", 0.04)}; transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1), border-color 0.4s ease, box-shadow 0.4s ease, background 0.4s ease !important; cursor: pointer; } .dm-opt-metric:hover { transform: translateY(-5px) scale(1.028) !important; background: ${rgba(COLORS.ink, 0.9)} !important; border-color: ${rgba(COLORS.cyan, 0.52)} !important; box-shadow: 0 18px 48px -8px ${rgba(COLORS.cyan, 0.25)}, 0 4px 12px -2px ${rgba(COLORS.cyan, 0.12)}, inset 0 1px 0 rgba(255, 255, 255, 0.1) !important; } .dm-opt-metric:hover .dm-opt-metric__sparkline { opacity: 0.72 !important; } .dm-opt-metric__sparkline { transition: opacity 0.4s ease; } @keyframes dmOptCardIn { to { opacity: 1; transform: translateY(0); } } .dm-opt-metric__top { display: flex; align-items: center; justify-content: space-between; } .dm-opt-metric__label { font-size: 10px; letter-spacing: 0.04em; color: ${COLORS.textDim}; text-transform: uppercase; } .dm-opt-metric__arrow { font-size: 11px; } .dm-opt-metric__value { margin-top: 6px; font-size: clamp(20px, 2.8vw, 32px); font-weight: 700; line-height: 1; } .dm-opt-metric__bar { margin-top: 10px; height: 3px; border-radius: 999px; background: ${rgba(COLORS.slate, 0.2)}; overflow: hidden; } .dm-opt-metric__fill { height: 100%; border-radius: 999px; transform-origin: left center; } /* ===== BOTTOM INSIGHT BAR ===== */ .dm-opt-insight { display: flex; align-items: center; justify-content: center; gap: 8px; max-width: 760px; margin: 10px auto 0; padding: 7px 18px; border-radius: 999px; background: ${rgba(COLORS.ink, 0.6)}; border: 1px solid ${rgba(COLORS.cyan, 0.12)}; backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); pointer-events: auto; } .dm-opt-insight__dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; background: ${COLORS.green}; box-shadow: 0 0 12px ${COLORS.green}; animation: dmOptPulse 2s ease-in-out infinite; } .dm-opt-insight__text { font-size: 10.5px; color: ${COLORS.textDim}; line-height: 1.3; letter-spacing: 0.03em; font-weight: 500; } .dm-opt-insight__text strong { color: #E2E8F0; font-weight: 700; } .dm-opt-insight__sep { width: 1px; height: 12px; flex-shrink: 0; background: ${rgba(COLORS.slate, 0.35)}; } /* ===== RESPONSIVE ===== */ @media (max-width: 1024px) { .dm-opt-panel { width: clamp(190px, 30vw, 280px); padding: 14px 16px; } .dm-opt-panel li { font-size: 11.5px; } .dm-opt-marker { width: 16px; height: 16px; font-size: 9px; } } @media (max-width: 767px) { .dm-opt { height: 200vh; } .dm-opt-card { top: 8px !important; left: 8px !important; right: 8px !important; bottom: 8px !important; border-radius: 24px !important; } .dm-opt-compare { top: auto; bottom: 148px; transform: none; flex-direction: row; align-items: stretch; gap: 6px; padding: 0 10px; } .dm-opt-panel { width: 50%; padding: 10px 11px; border-radius: 14px; } .dm-opt-panel ul { gap: 4px; } .dm-opt-panel li { font-size: 10px; } .dm-opt-panel li::before { display: none !important; } .dm-opt-marker { width: 14px; height: 14px; font-size: 8px; border-radius: 4px; } .dm-opt-panel h3 { margin: 6px 0 5px; font-size: 14px; } .dm-opt-panel__badge { font-size: 8px; padding: 3px 7px; } .dm-opt-metrics { grid-template-columns: repeat(5, 1fr); gap: 4px; } .dm-opt-metric { padding: 7px 5px; border-radius: 10px; } .dm-opt-metric__label { font-size: 7.5px; letter-spacing: 0; } .dm-opt-metric__value { font-size: 14px; } .dm-opt-metric__bar { margin-top: 6px; } .dm-opt-head h2 { font-size: 22px; margin: 6px 0 4px; } .dm-opt-head p { font-size: 10.5px; } .dm-opt-phases { display: none; } .dm-opt-steps { gap: 0; } .dm-opt-steps__pill { padding: 3px 6px; } .dm-opt-steps__icon { font-size: 9px; } .dm-opt-steps__text { font-size: 7.5px; } .dm-opt-steps__line { width: 6px; } .dm-opt-insight { padding: 5px 10px; gap: 5px; } .dm-opt-insight__text { font-size: 8.5px; } .dm-opt-insight__sep { height: 10px; } } @media (prefers-reduced-motion: reduce) { .dm-opt-pulse { animation: none; } .dm-opt-metric { animation: none; opacity: 1; transform: none; } .dm-opt-insight__dot { animation: none; } .dm-opt-card::before { animation: none; } } `;