update miletruth page and remove unwanted files

This commit is contained in:
2026-06-03 13:42:12 +05:30
parent 3bad62851c
commit 6eea5636fb
153 changed files with 6089 additions and 36024 deletions

View File

@@ -0,0 +1,516 @@
"use client";
import React, { useEffect, useRef, useState } from "react";
import dynamic from "next/dynamic";
import { motion, useMotionValue, useTransform, type MotionValue } from "framer-motion";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { STAGES, N } from "./theme";
const StrategyCanvas = dynamic(() => import("./StrategyCanvas"), { ssr: false });
/** Center of each stage's scroll window (0…1). */
const CENTER = (i: number) => i / (N - 1);
/** Persistent top rail: the 5 stages, current one highlighted. */
function StageRail({ active }: { active: number }) {
return (
<div className="dm-st-rail" aria-hidden>
{STAGES.map((s, i) => {
const state = i < active ? "done" : i === active ? "current" : "todo";
return (
<React.Fragment key={s.n}>
{i > 0 && <span className={`dm-st-rail__line is-${i <= active ? "on" : "off"}`} />}
<div className={`dm-st-rail__step is-${state}`} style={{ ["--c" as string]: s.theme }}>
<span className="dm-st-rail__num">{i < active ? "✓" : s.n}</span>
<span className="dm-st-rail__title">{s.kicker}</span>
</div>
</React.Fragment>
);
})}
</div>
);
}
/** A cross-fading glass content card pinned to one side, themed per stage. */
function StageCard({
i,
scroll,
side,
children,
}: {
i: number;
scroll: MotionValue<number>;
side: "left" | "right";
children: React.ReactNode;
}) {
const c = CENTER(i);
const opacity = useTransform(scroll, [c - 0.14, c - 0.06, c + 0.06, c + 0.14], [0, 1, 1, 0]);
const y = useTransform(scroll, [c - 0.14, c - 0.05], [34, 0]);
const s = STAGES[i];
return (
<motion.div
className={`dm-st-card-story is-${side}`}
style={{ opacity, y, ["--c" as string]: s.theme }}
>
<div className="dm-st-card-story__head">
<span className="dm-st-pillar__num">{s.n}</span>
<span className="dm-st-pillar__kicker">{s.kicker}</span>
</div>
{children}
</motion.div>
);
}
/**
* "Strategy" — a premium, Apple-keynote-style 3D scroll-storytelling section.
* A single GSAP ScrollTrigger maps scroll to a normalized progress that drives
* the R3F camera through five floating glass stages while DOM glass cards
* cross-fade in lockstep. Pins via a self-managed fixed element (the site's
* fixed header + an ancestor `overflow:hidden` break CSS sticky / GSAP pin).
*/
export default function StrategySection({ connected = false }: { connected?: boolean } = {}) {
const containerRef = useRef<HTMLDivElement>(null);
const progressRef = useRef(0);
const scroll = useMotionValue(0);
const [pinState, setPinState] = useState<"before" | "pinned" | "after">("before");
const [active, setActive] = useState(0);
const [mountScene, setMountScene] = useState(false);
const [sceneActive, setSceneActive] = useState(false);
const [isMobile, setIsMobile] = useState(false);
const [reduced, setReduced] = useState(false);
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); };
}, []);
useEffect(() => {
const el = containerRef.current;
if (!el) return;
const mountIo = new IntersectionObserver(
(entries) => {
if (entries.some((e) => e.isIntersecting)) {
setMountScene(true);
setSceneActive(true);
mountIo.disconnect();
}
},
{ rootMargin: "70% 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(); };
}, []);
useEffect(() => {
const el = containerRef.current;
if (!el) return;
gsap.registerPlugin(ScrollTrigger);
let lastPin: "before" | "pinned" | "after" = "before";
let lastActive = 0;
const st = ScrollTrigger.create({
trigger: el,
start: "top top",
end: "bottom bottom",
scrub: 0.5,
invalidateOnRefresh: true,
onUpdate: (self) => {
const p = self.progress;
progressRef.current = p;
scroll.set(p);
const ns = p <= 0.0002 ? "before" : p >= 0.9998 ? "after" : "pinned";
if (ns !== lastPin) { lastPin = ns; setPinState(ns); }
const na = Math.round(p * (N - 1));
if (na !== lastActive) { lastActive = na; setActive(na); }
},
});
const refresh = setTimeout(() => ScrollTrigger.refresh(), 300);
return () => { clearTimeout(refresh); st.kill(); };
}, [scroll]);
// Intro hint fades out as the journey begins.
const introOpacity = useTransform(scroll, [0, 0.03, 0.06], [1, 1, 0]);
// Persistent header fades in after the intro.
const headerOpacity = useTransform(scroll, [0.02, 0.07], [0, 1]);
return (
<section
ref={containerRef}
className={`dm-st is-${pinState}${connected ? " is-connected" : ""}`}
aria-label="Strategy — Happier Riders. Higher Fulfillment."
>
<div className="dm-st-sticky">
<div className="dm-st-card">
{mountScene && (
<div className="dm-st-canvas">
<StrategyCanvas progress={progressRef} reduced={reduced} isMobile={isMobile} active={sceneActive} />
</div>
)}
<div className="dm-st-ui">
{/* Persistent header */}
<motion.div className="dm-st-top" style={{ opacity: headerOpacity }}>
<div className="dm-st-eyebrow"><span className="dm-st-dot" /> MileTruth Strategy Engine</div>
<StageRail active={active} />
</motion.div>
{/* Intro hint */}
<motion.div className="dm-st-scrollhint" style={{ opacity: introOpacity }}>
<span>Scroll to follow the strategy</span>
<span className="dm-st-arrow"></span>
</motion.div>
{/* STAGE 01 — INPUT (green): orders + riders enter the system */}
<StageCard i={0} scroll={scroll} side="left">
<h3 className="dm-st-pillar__title">Orders &amp; riders enter the system</h3>
<div className="dm-st-grid2">
<div className="dm-st-tile">
<span className="dm-st-tile__ico">📄</span>
<span className="dm-st-tile__num">59</span>
<span className="dm-st-tile__lbl">Orders</span>
<span className="dm-st-tile__sub">Order intake</span>
</div>
<div className="dm-st-tile">
<span className="dm-st-tile__ico">🧑</span>
<span className="dm-st-tile__num">4</span>
<span className="dm-st-tile__lbl">Total Riders</span>
<span className="dm-st-tile__sub">Available fleet</span>
</div>
</div>
<div className="dm-st-file">
<span className="dm-st-file__ico"></span>
<span className="dm-st-file__name">orders.csv</span>
<span className="dm-st-file__meta">59 rows · uploaded</span>
<span className="dm-st-file__ok"></span>
</div>
<ul className="dm-st-riders">
{[
{ a: "A", name: "Rider A", v: "EV Bike", cap: "12 orders" },
{ a: "B", name: "Rider B", v: "Auto", cap: "18 orders" },
{ a: "C", name: "Rider C", v: "Cargo Truck", cap: "20 orders" },
{ a: "D", name: "Rider D", v: "EV Van", cap: "9 orders" },
].map((r) => (
<li key={r.a} className="dm-st-rider">
<span className="dm-st-rider__av">{r.a}<i /></span>
<span className="dm-st-rider__name">{r.name}</span>
<span className="dm-st-rider__veh">{r.v}</span>
<span className="dm-st-rider__cap">{r.cap}</span>
</li>
))}
</ul>
</StageCard>
{/* STAGE 02 — PARALLEL EXECUTION (purple): 6 strategies at once */}
<StageCard i={1} scroll={scroll} side="right">
<h3 className="dm-st-pillar__title">Six strategies, evaluated in parallel</h3>
<div className="dm-st-engines">
<div className="dm-st-engine">
<div className="dm-st-engine__head"><span className="dm-st-engine__name">Legacy Engine</span><span className="dm-st-engine__tag">Baseline</span></div>
<div className="dm-st-pills">
{["Proximity", "Balanced", "Fuel Saver"].map((p) => <span key={p} className="dm-st-pill">{p}</span>)}
</div>
</div>
<div className="dm-st-engine is-unified">
<div className="dm-st-engine__head"><span className="dm-st-engine__name">Unified Engine</span><span className="dm-st-engine__tag dm-st-engine__tag--u">MileTruth</span></div>
<div className="dm-st-pills">
{["EV Aware", "Multi Trip", "Time Aware"].map((p) => <span key={p} className="dm-st-pill dm-st-pill--u">{p}</span>)}
</div>
</div>
</div>
<p className="dm-st-foot"><span className="dm-st-livedot" /> All 6 strategies run at the same time</p>
</StageCard>
{/* STAGE 03 — SMART OPTIMIZATION (blue): validation pipeline */}
<StageCard i={2} scroll={scroll} side="left">
<h3 className="dm-st-pillar__title">Routes validated &amp; optimized</h3>
<div className="dm-st-pipe">
{[
{ ico: "⚙️", name: "VRP Optimizer", desc: "Google OR-Tools solver" },
{ ico: "🔋", name: "Battery Simulation", desc: "EV range & charging feasibility" },
{ ico: "⏱️", name: "SLA Validator", desc: "ETA vs promised window" },
].map((m, j) => (
<React.Fragment key={m.name}>
{j > 0 && <span className="dm-st-pipe__arrow"><i /></span>}
<div className="dm-st-pipe__node">
<span className="dm-st-pipe__ico">{m.ico}</span>
<span className="dm-st-pipe__name">{m.name}</span>
<span className="dm-st-pipe__desc">{m.desc}</span>
</div>
</React.Fragment>
))}
</div>
</StageCard>
{/* STAGE 04 — PERFORMANCE GRADING (orange): every strategy scored */}
<StageCard i={3} scroll={scroll} side="right">
<h3 className="dm-st-pillar__title">Every strategy is scored</h3>
<div className="dm-st-stars"><span className="dm-st-stars__on"></span><span className="dm-st-stars__off"></span><span className="dm-st-stars__txt">4.5 / 5 grade</span></div>
<ul className="dm-st-metrics">
{[
{ name: "Fulfillment Rate", score: "88%", w: 88, status: "Good", desc: "Orders delivered vs total" },
{ name: "SLA Compliance", score: "95%", w: 95, status: "Pass", desc: "On-time within window" },
{ name: "Efficiency Score", score: "92", w: 92, status: "Strong", desc: "Distance & fleet usage" },
{ name: "Battery & Route", score: "OK", w: 100, status: "Feasible", desc: "EV range respected" },
].map((m) => (
<li key={m.name} className="dm-st-metric">
<span className="dm-st-metric__name">{m.name}</span>
<span className="dm-st-metric__bar"><i style={{ width: `${m.w}%` }} /></span>
<span className="dm-st-metric__score">{m.score}</span>
<span className="dm-st-metric__status"> {m.status}</span>
<span className="dm-st-metric__desc">{m.desc}</span>
</li>
))}
</ul>
</StageCard>
{/* STAGE 05 — STRATEGY COMPARISON (red, hero): the winner */}
<StageCard i={4} scroll={scroll} side="right">
<div className="dm-st-winner">
<span className="dm-st-winner__eyebrow">Best strategy recommendation</span>
<div className="dm-st-winner__name"><span className="dm-st-trophy">🏆</span> EV Aware</div>
<span className="dm-st-winner__grade">High Performance Grade</span>
</div>
<div className="dm-st-hero">
<div className="dm-st-hero__ring">
<span className="dm-st-hero__pct">88%</span>
<span className="dm-st-hero__sub">Score</span>
</div>
<ul className="dm-st-wins">
<li><strong>52/59</strong> Orders Fulfilled</li>
<li><strong>88%</strong> Performance Score</li>
<li><strong>3</strong> SLA Violations</li>
<li><strong>A</strong> Performance Grade</li>
</ul>
</div>
</StageCard>
</div>
</div>
</div>
<style>{styles}</style>
</section>
);
}
const styles = `
.dm-st { position: relative; height: 620vh; background: transparent; }
.dm-st-sticky { position: absolute; top: 0; left: 0; width: 100%; height: 100vh; overflow: hidden; }
.dm-st.is-pinned .dm-st-sticky { position: fixed; top: 0; left: 0; }
.dm-st.is-after .dm-st-sticky { position: absolute; top: auto; bottom: 0; }
.dm-st-card {
position: absolute !important; inset: 16px !important;
border-radius: 28px !important; overflow: hidden !important;
background: radial-gradient(120% 100% at 50% 0%, #ffffff 0%, #eef1f6 60%, #e6eaf2 100%) !important;
border: 1px solid rgba(15,23,42,0.08) !important;
box-shadow: 0 30px 90px -34px rgba(15,23,42,0.4) !important;
box-sizing: border-box !important;
}
@media (max-width: 767px) { .dm-st-card { inset: 10px !important; border-radius: 20px !important; } }
/* Connected mode (inside Workflow 3): flatten the card's bottom so the Strategy
content card below butts directly against it — same seam as Workflow 1 & 2. */
.dm-st.is-connected .dm-st-card {
top: 16px !important; left: 16px !important; right: 16px !important; bottom: 0 !important;
border-radius: 28px 28px 0 0 !important; border-bottom: none !important;
}
@media (max-width: 767px) {
.dm-st.is-connected .dm-st-card {
top: 10px !important; left: 10px !important; right: 10px !important; bottom: 0 !important;
border-radius: 20px 20px 0 0 !important;
}
}
.dm-st-canvas { position: absolute; inset: 0; z-index: 1; }
.dm-st-canvas canvas { display: block; }
.dm-st-ui { position: absolute; inset: 0; z-index: 4; pointer-events: none;
font-family: var(--font-space-grotesk), var(--font-manrope), system-ui, sans-serif; color: #0f172a; }
/* ---- Persistent header: title + 5-stage rail ---- */
.dm-st-top { position: absolute; top: clamp(96px, 13vh, 128px); left: 0; right: 0; z-index: 5;
display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 0 16px; }
.dm-st-eyebrow { display: inline-flex; align-items: center; gap: 8px; font-size: 11px; line-height: 1.35;
letter-spacing: 0.28em; text-transform: uppercase; color: #475569; padding: 9px 18px; border-radius: 999px;
background: rgba(255,255,255,0.72); border: 1px solid rgba(15,23,42,0.08); backdrop-filter: blur(10px); white-space: nowrap; }
.dm-st-dot { width: 6px; height: 6px; border-radius: 50%; background: #6366f1; box-shadow: 0 0 10px #6366f1; }
.dm-st-rail { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; max-width: 980px; }
.dm-st-rail__step { display: inline-flex; align-items: center; gap: 7px; padding: 5px 11px; border-radius: 999px;
background: rgba(255,255,255,0.7); border: 1px solid rgba(15,23,42,0.08); backdrop-filter: blur(8px);
transition: all 0.45s cubic-bezier(0.22,1,0.36,1); }
.dm-st-rail__num { width: 18px; height: 18px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
font-size: 10px; font-weight: 800; color: #64748b; background: rgba(15,23,42,0.06); }
.dm-st-rail__title { font-size: 11px; font-weight: 600; letter-spacing: 0.02em; color: #64748b; white-space: nowrap; }
.dm-st-rail__step.is-current { background: color-mix(in srgb, var(--c) 16%, white); border-color: var(--c);
box-shadow: 0 0 22px -6px var(--c); }
.dm-st-rail__step.is-current .dm-st-rail__num { background: var(--c); color: #fff; }
.dm-st-rail__step.is-current .dm-st-rail__title { color: #0f172a; }
.dm-st-rail__step.is-done .dm-st-rail__num { background: #22C55E; color: #fff; }
.dm-st-rail__step.is-done .dm-st-rail__title { color: #334155; }
.dm-st-rail__line { width: 14px; height: 1px; background: rgba(15,23,42,0.14); margin: 0 3px; transition: background 0.45s ease; }
.dm-st-rail__line.is-on { background: var(--c, #22C55E); }
.dm-st-scrollhint { position: absolute; bottom: clamp(26px, 6vh, 60px); left: 50%; transform: translateX(-50%);
display: flex; flex-direction: column; align-items: center; gap: 8px; font-size: 12px; letter-spacing: 0.12em;
color: #64748b; text-transform: uppercase; text-align: center; }
.dm-st-arrow { font-size: 18px; animation: dmStBob 1.8s ease-in-out infinite; }
@keyframes dmStBob { 0%,100% { transform: translateY(0); opacity: 0.5; } 50% { transform: translateY(6px); opacity: 1; } }
/* ---- Per-stage glass content card ---- */
.dm-st-card-story { position: absolute; bottom: clamp(24px, 6vh, 64px); width: min(484px, 88vw);
pointer-events: auto; will-change: opacity, transform; padding: 20px 22px; border-radius: 20px;
background: rgba(255,255,255,0.94); border: 1px solid rgba(15,23,42,0.08);
/* backdrop blur removed — card cross-fades/translates per scroll-stage; blur was the
heaviest per-frame cost on this section. Near-opaque white keeps the glass look. */
border-top: 3px solid var(--c);
box-shadow: 0 28px 70px -34px rgba(15,23,42,0.5); }
.dm-st-card-story.is-left { left: clamp(18px, 5vw, 72px); }
.dm-st-card-story.is-right { right: clamp(18px, 5vw, 72px); }
.dm-st-card-story__head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.dm-st-pillar__num { font-size: 12px; font-weight: 800; letter-spacing: 0.1em; color: #fff;
background: var(--c); border-radius: 7px; padding: 3px 8px; }
.dm-st-pillar__kicker { font-size: clamp(11px, 1.1vw, 13px); font-weight: 700; letter-spacing: 0.16em;
text-transform: uppercase; color: var(--c); }
.dm-st .dm-st-pillar__title { margin: 0 0 14px !important; padding: 0 !important; color: #0f172a !important;
font-weight: 700 !important; text-transform: none !important; letter-spacing: -0.015em !important;
font-size: clamp(18px, 2vw, 26px) !important; line-height: 1.16 !important; }
.dm-st .dm-st-pillar__title--hero { font-size: clamp(22px, 2.6vw, 34px) !important;
background: linear-gradient(90deg, #C01227, #E2354A) !important; -webkit-background-clip: text !important;
background-clip: text !important; -webkit-text-fill-color: transparent !important; }
.dm-st-foot { margin: 12px 0 0; font-size: clamp(12px, 1.1vw, 13.5px); line-height: 1.5; color: #475569;
display: flex; align-items: center; gap: 8px; }
.dm-st-livedot { width: 8px; height: 8px; border-radius: 50%; background: var(--c); box-shadow: 0 0 0 0 var(--c);
animation: dmStPulse 1.8s ease-out infinite; }
@keyframes dmStPulse { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--c) 55%, transparent); } 100% { box-shadow: 0 0 0 9px transparent; } }
/* In-scene 3D labels (drei <Html>) — crisp glass chips floating in the WebGL scene */
.dm-st3d-file, .dm-st3d-count, .dm-st3d-ai, .dm-st3d-chip {
font-family: var(--font-space-grotesk), var(--font-manrope), system-ui, sans-serif;
pointer-events: none; user-select: none; white-space: nowrap; transition: opacity 0.2s linear; }
.dm-st3d-file, .dm-st3d-ai {
display: inline-flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 700; color: #0f172a;
background: rgba(255,255,255,0.88); border: 1px solid rgba(34,197,94,0.4); border-radius: 999px;
padding: 6px 13px; box-shadow: 0 8px 22px -12px rgba(34,197,94,0.7); backdrop-filter: blur(8px); }
.dm-st3d-count { font-size: 15px; font-weight: 800; color: #0f172a; background: rgba(255,255,255,0.9);
border: 1px solid rgba(34,197,94,0.45); border-radius: 12px; padding: 6px 14px;
box-shadow: 0 10px 26px -12px rgba(34,197,94,0.8); backdrop-filter: blur(8px); }
.dm-st3d-count span { color: #16a34a; font-size: 19px; }
.dm-st3d-chip { display: inline-flex; align-items: center; gap: 8px; background: rgba(255,255,255,0.92);
border: 1px solid rgba(34,197,94,0.4); border-radius: 12px; padding: 6px 11px;
box-shadow: 0 10px 26px -14px rgba(15,23,42,0.7); backdrop-filter: blur(8px); }
.dm-st3d-chip__ico { font-size: 17px; }
.dm-st3d-chip__txt { display: flex; flex-direction: column; line-height: 1.15; }
.dm-st3d-chip__txt b { font-size: 12.5px; font-weight: 800; color: #0f172a; }
.dm-st3d-chip__txt { font-size: 10.5px; color: #475569; }
/* STAGE 01 — Input */
.dm-st-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 10px; }
.dm-st-tile { position: relative; background: color-mix(in srgb, var(--c) 7%, white); border: 1px solid color-mix(in srgb, var(--c) 22%, white);
border-radius: 14px; padding: 12px 14px; display: grid; grid-template-columns: auto 1fr; grid-template-rows: auto auto; column-gap: 10px; align-items: center; }
.dm-st-tile__ico { grid-row: 1 / 3; font-size: 24px; }
.dm-st-tile__num { font-size: 26px; font-weight: 800; color: #0f172a; line-height: 1; }
.dm-st-tile__lbl { font-size: 12px; font-weight: 700; color: #334155; }
.dm-st-tile__sub { grid-column: 1 / 3; margin-top: 4px; font-size: 10.5px; letter-spacing: 0.04em; text-transform: uppercase; color: #64748b; }
.dm-st-file { display: flex; align-items: center; gap: 9px; margin-bottom: 12px; padding: 9px 12px; border-radius: 12px;
background: rgba(15,23,42,0.04); border: 1px dashed rgba(15,23,42,0.18); }
.dm-st-file__ico { font-size: 15px; }
.dm-st-file__name { font-size: 13px; font-weight: 700; color: #0f172a; }
.dm-st-file__meta { font-size: 11.5px; color: #64748b; }
.dm-st-file__ok { margin-left: auto; font-size: 12px; font-weight: 800; color: #22C55E; }
.dm-st-riders { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.dm-st-rider { display: grid; grid-template-columns: 26px 1fr auto auto; align-items: center; gap: 9px;
padding: 6px 8px; border-radius: 10px; background: rgba(15,23,42,0.03); }
.dm-st-rider__av { position: relative; width: 26px; height: 26px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
font-size: 11px; font-weight: 800; color: #fff; background: linear-gradient(135deg, var(--c), color-mix(in srgb, var(--c) 60%, #1e293b)); }
.dm-st-rider__av i { position: absolute; right: -1px; bottom: -1px; width: 8px; height: 8px; border-radius: 50%; background: #22C55E; border: 2px solid #fff; }
.dm-st-rider__name { font-size: 12.5px; font-weight: 700; color: #0f172a; }
.dm-st-rider__veh { font-size: 11px; font-weight: 600; color: #475569; padding: 2px 8px; border-radius: 999px; background: rgba(15,23,42,0.06); }
.dm-st-rider__cap { font-size: 11px; color: #64748b; white-space: nowrap; }
/* STAGE 02 — Parallel execution */
.dm-st-engines { display: grid; gap: 10px; }
.dm-st-engine { padding: 11px 12px; border-radius: 14px; background: rgba(15,23,42,0.03); border: 1px solid rgba(15,23,42,0.07); }
.dm-st-engine.is-unified { background: color-mix(in srgb, var(--c) 8%, white); border-color: color-mix(in srgb, var(--c) 28%, white); }
.dm-st-engine__head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.dm-st-engine__name { font-size: 13px; font-weight: 800; color: #0f172a; }
.dm-st-engine__tag { font-size: 9.5px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: #64748b;
background: rgba(15,23,42,0.07); padding: 2px 7px; border-radius: 6px; }
.dm-st-engine__tag--u { color: #fff; background: var(--c); }
.dm-st-pills { display: flex; flex-wrap: wrap; gap: 7px; }
.dm-st-pill { font-size: 12px; font-weight: 700; color: #334155; padding: 6px 12px; border-radius: 999px;
background: rgba(255,255,255,0.9); border: 1px solid rgba(15,23,42,0.12); }
.dm-st-pill--u { color: #0f172a; background: color-mix(in srgb, var(--c) 14%, white); border-color: color-mix(in srgb, var(--c) 40%, white); }
/* STAGE 03 — Optimization pipeline */
.dm-st-pipe { display: grid; gap: 0; }
.dm-st-pipe__node { display: grid; grid-template-columns: auto 1fr; grid-template-rows: auto auto; column-gap: 11px; align-items: center;
padding: 11px 14px; border-radius: 14px; background: rgba(255,255,255,0.92);
border: 1px solid color-mix(in srgb, var(--c) 30%, white); box-shadow: 0 8px 22px -14px var(--c); }
.dm-st-pipe__ico { grid-row: 1 / 3; font-size: 22px; }
.dm-st-pipe__name { font-size: 13.5px; font-weight: 800; color: #0f172a; }
.dm-st-pipe__desc { font-size: 11.5px; color: #64748b; }
.dm-st-pipe__arrow { display: flex; align-items: center; justify-content: center; height: 22px; }
.dm-st-pipe__arrow i { position: relative; width: 2px; height: 22px; background: linear-gradient(180deg, color-mix(in srgb, var(--c) 50%, transparent), var(--c)); overflow: visible; }
.dm-st-pipe__arrow i::after { content: ""; position: absolute; left: 50%; top: -4px; width: 6px; height: 6px; border-radius: 50%;
background: var(--c); box-shadow: 0 0 8px var(--c); transform: translateX(-50%); animation: dmStFlow 1.4s linear infinite; }
@keyframes dmStFlow { 0% { top: -4px; opacity: 0; } 20% { opacity: 1; } 100% { top: 22px; opacity: 0; } }
/* STAGE 04 — Performance grading */
.dm-st-stars { display: flex; align-items: center; gap: 6px; margin-bottom: 12px; }
.dm-st-stars__on { color: var(--c); letter-spacing: 2px; font-size: 16px; }
.dm-st-stars__off { color: rgba(15,23,42,0.18); font-size: 16px; }
.dm-st-stars__txt { font-size: 12px; font-weight: 700; color: #475569; margin-left: 4px; }
.dm-st-metrics { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.dm-st-metric { display: grid; grid-template-columns: 1fr 70px auto; grid-template-rows: auto auto; column-gap: 10px; row-gap: 3px; align-items: center; }
.dm-st-metric__name { font-size: 12.5px; font-weight: 700; color: #0f172a; }
.dm-st-metric__bar { grid-column: 1 / 2; grid-row: 2; height: 6px; border-radius: 999px; background: rgba(15,23,42,0.08); overflow: hidden; }
.dm-st-metric__bar i { display: block; height: 100%; border-radius: 999px; background: var(--c); }
.dm-st-metric__score { grid-column: 2; grid-row: 1 / 3; font-size: 17px; font-weight: 800; color: #0f172a; text-align: right; }
.dm-st-metric__status { grid-column: 3; grid-row: 1 / 3; font-size: 11px; font-weight: 800; color: #16a34a;
background: rgba(34,197,94,0.12); border: 1px solid rgba(34,197,94,0.3); padding: 3px 8px; border-radius: 999px; white-space: nowrap; }
.dm-st-metric__desc { grid-column: 1 / 2; grid-row: 1; font-size: 10.5px; color: #64748b; align-self: end; display: none; }
/* STAGE 05 — Strategy comparison (hero) */
.dm-st-winner { margin-bottom: 14px; }
.dm-st-winner__eyebrow { display: block; font-size: 10.5px; font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase; color: #64748b; }
.dm-st-winner__name { display: flex; align-items: center; gap: 10px; margin: 4px 0; font-size: clamp(24px, 2.8vw, 34px); font-weight: 800; color: #0f172a; letter-spacing: -0.02em; }
.dm-st-winner__grade { display: inline-block; font-size: 11px; font-weight: 800; letter-spacing: 0.04em; color: #fff;
background: linear-gradient(90deg, #C01227, #E2354A); padding: 4px 11px; border-radius: 999px; }
.dm-st-trophy { font-size: 32px; filter: drop-shadow(0 8px 18px rgba(192,18,39,0.4)); animation: dmStFloat 3s ease-in-out infinite; }
@keyframes dmStFloat { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-5px); } }
.dm-st-hero { display: flex; align-items: center; gap: 20px; }
.dm-st-hero__ring { position: relative; flex-shrink: 0; width: 96px; height: 96px; border-radius: 50%; display: flex; flex-direction: column;
align-items: center; justify-content: center; background: conic-gradient(#C01227 88%, rgba(15,23,42,0.1) 0); }
.dm-st-hero__ring::after { content: ""; position: absolute; inset: 9px; border-radius: 50%; background: #fff; }
.dm-st-hero__pct { position: relative; z-index: 1; font-size: 24px; font-weight: 800; color: #C01227; }
.dm-st-hero__sub { position: relative; z-index: 1; font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: #64748b; }
.dm-st-wins { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.dm-st-wins li { font-size: 13px; color: #334155; display: flex; align-items: baseline; gap: 8px; }
.dm-st-wins strong { color: #C01227; font-weight: 800; min-width: 48px; }
@media (max-width: 1000px) {
.dm-st-rail__title { display: none; }
.dm-st-rail__step { padding: 5px 7px; }
.dm-st-rail__line { width: 9px; }
}
@media (max-width: 767px) {
.dm-st { height: 560vh; }
.dm-st-card-story { left: 0 !important; right: 0 !important; margin: 0 auto; width: calc(100% - 28px);
bottom: clamp(18px, 4vh, 40px); padding: 15px 16px; }
.dm-st-rider__cap { display: none; }
}
@media (prefers-reduced-motion: reduce) {
.dm-st-arrow, .dm-st-trophy { animation: none !important; }
}
`;