update doormile wings page

This commit is contained in:
2026-07-06 17:12:39 +05:30
parent 09bfb957e6
commit fc190343eb
27 changed files with 2696 additions and 1864 deletions

View File

@@ -0,0 +1,392 @@
"use client";
import { useEffect, useRef } from "react";
import { ScrollReveal, StaggerChildren } from "@/animations/Reveal";
const CAPABILITIES = [
{
title: "Demand Forecasting",
desc: "AI-driven forward projection of cargo demand, preemptively positioning aircraft and ground capacity.",
icon: (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.25" strokeLinecap="round" strokeLinejoin="round">
<path d="M3 3v18h18" />
<path d="M7 14l4-4 3 3 6-7" />
</svg>
),
},
{
title: "Dynamic Pricing",
desc: "Real-time rate adjustments that track market capacity fluctuations and optimize yield.",
icon: (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.25" strokeLinecap="round" strokeLinejoin="round">
<circle cx="12" cy="12" r="10" />
<path d="M9.5 9.5c0-1.4 1.1-2.3 2.5-2.3s2.5.9 2.5 2c0 1.6-2.2 1.8-2.5 3.3M12 17h.01" />
</svg>
),
},
{
title: "Route Optimization",
desc: "Dynamic scheduling for ground EV pickups and flights that bypasses congestion for the fastest path.",
icon: (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.25" strokeLinecap="round" strokeLinejoin="round">
<line x1="5" y1="12" x2="19" y2="12" />
<polyline points="13 6 19 12 13 18" />
</svg>
),
},
{
title: "Load Balancing",
desc: "Automated weight-and-balance modeling for optimal, safe aircraft load layout within minutes.",
icon: (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.25" strokeLinecap="round" strokeLinejoin="round">
<path d="M12 3v18M5 8l7-5 7 5M5 8v9a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8" />
</svg>
),
},
{
title: "Predictive Maintenance",
desc: "Continuous telemetry monitoring triggers preemptive alerts, drastically reducing aircraft downtime.",
icon: (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.25" strokeLinecap="round" strokeLinejoin="round">
<path d="M22 12h-6l-4 8-4-16-4 8H2" />
</svg>
),
},
{
title: "Real-Time Tracking",
desc: "End-to-end sensor monitoring keeps shippers, airline, and EV operators updated on exact shipment state.",
icon: (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.25" strokeLinecap="round" strokeLinejoin="round">
<path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7-11-7-11-7Z" />
<circle cx="12" cy="12" r="3" />
</svg>
),
},
];
export default function WingsMileTruth() {
const canvasRef = useRef<HTMLCanvasElement>(null);
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const ctx = canvas.getContext("2d");
if (!ctx) return;
const reduced = window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
let width = (canvas.width = canvas.offsetWidth);
let height = (canvas.height = canvas.offsetHeight);
const handleResize = () => {
width = canvas.width = canvas.offsetWidth;
height = canvas.height = canvas.offsetHeight;
};
window.addEventListener("resize", handleResize);
const nodes = [
{ x: 0.12, y: 0.5 },
{ x: 0.34, y: 0.25 },
{ x: 0.56, y: 0.65 },
{ x: 0.78, y: 0.3 },
{ x: 0.92, y: 0.6 },
];
const particles = [
{ from: 0, to: 1, t: 0, speed: 0.006 },
{ from: 1, to: 2, t: 0.4, speed: 0.005 },
{ from: 2, to: 3, t: 0.15, speed: 0.007 },
{ from: 3, to: 4, t: 0.6, speed: 0.005 },
];
let raf: number;
const draw = () => {
ctx.clearRect(0, 0, width, height);
ctx.lineWidth = 1.5;
ctx.setLineDash([6, 6]);
ctx.strokeStyle = "rgba(200, 16, 46, 0.16)";
ctx.beginPath();
for (let i = 0; i < nodes.length - 1; i++) {
ctx.moveTo(nodes[i].x * width, nodes[i].y * height);
ctx.lineTo(nodes[i + 1].x * width, nodes[i + 1].y * height);
}
ctx.stroke();
ctx.setLineDash([]);
if (!reduced) {
particles.forEach((p) => {
p.t += p.speed;
if (p.t >= 1) p.t = 0;
const a = nodes[p.from];
const b = nodes[p.to];
const x = a.x * width + (b.x * width - a.x * width) * p.t;
const y = a.y * height + (b.y * height - a.y * height) * p.t;
ctx.beginPath();
ctx.arc(x, y, 3.5, 0, Math.PI * 2);
ctx.fillStyle = "#c8102e";
ctx.shadowColor = "#c8102e";
ctx.shadowBlur = 10;
ctx.fill();
ctx.shadowBlur = 0;
});
}
nodes.forEach((n) => {
const x = n.x * width;
const y = n.y * height;
ctx.beginPath();
ctx.arc(x, y, 7, 0, Math.PI * 2);
ctx.fillStyle = "rgba(200, 16, 46, 0.1)";
ctx.fill();
ctx.beginPath();
ctx.arc(x, y, 3, 0, Math.PI * 2);
ctx.fillStyle = "rgba(255, 255, 255, 0.25)";
ctx.fill();
});
if (!reduced) raf = requestAnimationFrame(draw);
};
draw();
return () => {
window.removeEventListener("resize", handleResize);
if (raf) cancelAnimationFrame(raf);
};
}, []);
return (
<>
<style
dangerouslySetInnerHTML={{
__html: `
.wmt-section {
position: relative;
width: calc(100% - 40px);
margin: 0 auto;
border-radius: 28px;
overflow: hidden;
box-sizing: border-box;
background: #09090b;
padding: clamp(64px, 8vw, 100px) clamp(24px, 5vw, 48px);
}
.wmt-canvas {
position: absolute;
inset: 0;
z-index: 0;
width: 100%;
height: 100%;
pointer-events: none;
opacity: 0.12;
}
.wmt-glow {
position: absolute;
width: 480px;
height: 480px;
border-radius: 50%;
pointer-events: none;
filter: blur(140px);
z-index: 0;
opacity: 0.06;
}
.wmt-glow.tl { left: -8%; top: -12%; background: radial-gradient(circle, #c8102e 0%, transparent 70%); }
.wmt-glow.br { right: -8%; bottom: -12%; background: radial-gradient(circle, #ff3b3b 0%, transparent 70%); }
.wmt-inner {
position: relative;
z-index: 1;
max-width: 1200px;
margin: 0 auto;
}
.wmt-header {
margin: 0 auto 48px auto;
max-width: 720px;
text-align: center;
}
.wmt-eyebrow {
font-size: 13px;
font-weight: 800;
letter-spacing: 2.5px;
text-transform: uppercase;
color: #c8102e;
margin-bottom: 16px;
}
.wmt-title {
font-size: clamp(28px, 3.4vw, 48px) !important;
font-weight: 800 !important;
letter-spacing: -0.03em !important;
line-height: 1.15 !important;
text-transform: none !important;
color: #ffffff !important;
margin: 0;
}
.wmt-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 18px;
margin-bottom: 20px;
}
.wmt-card {
min-width: 0;
position: relative;
background: rgba(255, 255, 255, 0.035);
border: 1px solid rgba(255, 255, 255, 0.07);
border-radius: 18px;
padding: 26px 22px;
transition: transform 0.5s cubic-bezier(0.16, 1, 0.3, 1), border-color 0.5s cubic-bezier(0.16, 1, 0.3, 1), background-color 0.5s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.5s cubic-bezier(0.16, 1, 0.3, 1);
}
.wmt-card:hover {
transform: translateY(-6px);
border-color: rgba(255, 255, 255, 0.16);
background-color: rgba(255, 255, 255, 0.055);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.35);
}
.wmt-card-icon {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 10px;
background: rgba(200, 16, 46, 0.12);
color: #ffffff;
margin-bottom: 18px;
}
.wmt-card-title {
font-size: 15.5px !important;
font-weight: 700 !important;
line-height: 1.3 !important;
text-transform: none !important;
color: #ffffff !important;
margin: 0 0 8px 0;
}
.wmt-card-desc {
font-size: 13px;
line-height: 1.55;
color: rgba(255, 255, 255, 0.55);
margin: 0;
}
.wmt-callout {
position: relative;
border-radius: 20px;
padding: 34px 32px;
background: linear-gradient(135deg, rgba(200, 16, 46, 0.95) 0%, rgba(110, 8, 26, 0.98) 100%);
border: 1px solid rgba(255, 255, 255, 0.15);
display: flex;
align-items: center;
justify-content: space-between;
gap: 24px;
flex-wrap: wrap;
overflow: hidden;
}
.wmt-callout::after {
content: "";
position: absolute;
inset: -1.5px;
border-radius: 20px;
background: linear-gradient(90deg, #c8102e, #ff3366, #ff0033, #c8102e);
background-size: 300% 100%;
animation: wmt-sweep 6s linear infinite;
z-index: -1;
opacity: 0.6;
}
@keyframes wmt-sweep {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
.wmt-callout-body { max-width: 640px; }
.wmt-callout-title {
font-size: 20px !important;
font-weight: 800 !important;
line-height: 1.3 !important;
text-transform: none !important;
color: #ffffff !important;
margin: 0 0 8px 0;
}
.wmt-callout-desc {
font-size: 14px;
line-height: 1.55;
color: rgba(255, 255, 255, 0.85);
margin: 0;
}
.wmt-callout-badge {
flex-shrink: 0;
font-size: 11.5px;
font-weight: 800;
letter-spacing: 1px;
text-transform: uppercase;
color: #ffffff;
background: rgba(255, 255, 255, 0.15);
border: 1px solid rgba(255, 255, 255, 0.25);
border-radius: 999px;
padding: 8px 16px;
}
@media (max-width: 1024px) {
.wmt-section { width: calc(100% - 24px); border-radius: 22px; }
.wmt-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 600px) {
.wmt-grid { grid-template-columns: 1fr; }
.wmt-callout { flex-direction: column; align-items: flex-start; }
}
`,
}}
/>
<section className="wmt-section" id="wings-miletruth">
<canvas ref={canvasRef} className="wmt-canvas" aria-hidden="true" />
<div className="wmt-glow tl" aria-hidden="true" />
<div className="wmt-glow br" aria-hidden="true" />
<div className="wmt-inner">
<ScrollReveal delay={0.05} duration={0.75} yOffset={25} className="wmt-header">
<div className="wmt-eyebrow">/ MileTruth&trade; AI /</div>
<h2 className="wmt-title">The intelligence layer behind every delivery</h2>
</ScrollReveal>
<StaggerChildren stagger={0.08} duration={0.65} yOffset={25} className="wmt-grid">
{CAPABILITIES.map((c) => (
<div key={c.title} className="wmt-card">
<div className="wmt-card-icon" aria-hidden="true">{c.icon}</div>
<h3 className="wmt-card-title">{c.title}</h3>
<p className="wmt-card-desc">{c.desc}</p>
</div>
))}
</StaggerChildren>
<ScrollReveal delay={0.15} duration={0.8} yOffset={25}>
<div className="wmt-callout">
<div className="wmt-callout-body">
<h3 className="wmt-callout-title">Digital Twin of the Logistics Network</h3>
<p className="wmt-callout-desc">
A live virtual model of every ground vehicle, terminal, and flight simulating
what-if scenarios before bottlenecks ever form.
</p>
</div>
<span className="wmt-callout-badge">SaaS Ready</span>
</div>
</ScrollReveal>
</div>
</section>
</>
);
}