/*!
* jQuery Cookie Plugin v1.4.1
* https://github.com/carhartl/jquery-cookie
*
* Copyright 2013 Klaus Hartl
* Released under the MIT license
*/
!function(e) {
"function" == typeof define && define.amd ? define(["jquery"], e) : "object" == typeof exports ? e(require("jquery")) : e(jQuery)
}(function(e) {
var n = /\+/g;
function o(e) {
return r.raw ? e : encodeURIComponent(e)
}
function i(e, o) {
var i = r.raw ? e : function(e) {
0 === e.indexOf('"') && (e = e.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, "\\"));
try {
return e = decodeURIComponent(e.replace(n, " ")),
r.json ? JSON.parse(e) : e
} catch (o) {}
}(e);
return "function" == typeof o ? o(i) : i
}
var r = e.cookie = function(n, t, u) {
if (t !== undefined && "function" != typeof t) {
if ("number" == typeof (u = e.extend({}, r.defaults, u)).expires) {
var c = u.expires
, f = u.expires = new Date;
f.setTime(+f + 864e5 * c)
}
return document.cookie = [o(n), "=", function(e) {
return o(r.json ? JSON.stringify(e) : String(e))
}(t), u.expires ? "; expires=" + u.expires.toUTCString() : "", u.path ? "; path=" + u.path : "", u.domain ? "; domain=" + u.domain : "", u.secure ? "; secure" : ""].join("")
}
for (var d, a = n ? undefined : {}, p = document.cookie ? document.cookie.split("; ") : [], s = 0, m = p.length; s < m; s++) {
var x = p[s].split("=")
, y = (d = x.shift(),
r.raw ? d : decodeURIComponent(d))
, k = x.join("=");
if (n && n === y) {
a = i(k, t);
break
}
n || (k = i(k)) === undefined || (a[y] = k)
}
return a
}
;
r.defaults = {},
e.removeCookie = function(n, o) {
return e.cookie(n) !== undefined && (e.cookie(n, "", e.extend({}, o, {
expires: -1
})),
!e.cookie(n))
}
});
/**
* Doormile — Premium Interactive Dashboard Logic
* Core Interactions: ALT Vision Toggles, Timeline Hover Highlights, Live AI Routing Simulator
*/
document.addEventListener('DOMContentLoaded', () => {
/* ==========================================================================
1. HEADER NAV SCROLL EFFECTS (For smooth page scrolling)
========================================================================== */
const sections = document.querySelectorAll('section');
// Smooth navigation anchor links
document.querySelectorAll('.scroll-arrow-link').forEach(link => {
link.addEventListener('click', function(e) {
e.preventDefault();
const targetId = this.getAttribute('href');
document.querySelector(targetId).scrollIntoView({
behavior: 'smooth'
});
});
});
/* ==========================================================================
2. INTERACTIVE STRATEGIC MOAT ACCORDION
========================================================================== */
const moatCards = document.querySelectorAll('.moat-card');
moatCards.forEach(card => {
card.addEventListener('click', () => {
// Remove active status from all cards
moatCards.forEach(c => c.classList.remove('active'));
// Activate current card
card.classList.add('active');
});
});
/* ==========================================================================
3. INTERACTIVE ALT VISION TOGGLES (Image 2 exact match)
========================================================================== */
const altPill1 = document.getElementById('alt-pill-1');
const altPill2 = document.getElementById('alt-pill-2');
const visionTitle = document.querySelector('.vision-main-title');
const visionSubtitle = document.querySelector('.vision-main-subtitle');
const vision2030CardHeading = document.querySelector('.glowing-vision-card .card-heading');
const vision2030CardText = document.querySelector('.glowing-vision-card .card-text');
// Alt 1 Copy Data
const alt1Data = {
title: 'The Intelligence Grid Behind Every Urban Mile',
subtitle: 'From Hyderabad EV pilot to nationwide AI logistics intelligence by 2030',
cardHeading: 'AI Pulse Layer',
cardText: 'Nationwide AI logistics grid reaching 15+ cities, empowering female micro-entrepreneurs.'
};
// Alt 2 Copy Data
const alt2Data = {
title: 'The Neural Backbone Behind Every Urban Mile',
subtitle: 'From Hyderabad EV pilot to a full algorithmic urban grid routing infrastructure by 2030',
cardHeading: 'Neural Backbone',
cardText: 'Resilient node logistics framework connecting metropolitan hubs through dynamic autonomous routing.'
};
function applyAltTransition(data, activePill, inactivePill) {
activePill.classList.add('active');
inactivePill.classList.remove('active');
// Smooth text transition
visionTitle.style.opacity = 0;
visionSubtitle.style.opacity = 0;
vision2030CardHeading.style.opacity = 0;
vision2030CardText.style.opacity = 0;
setTimeout(() => {
visionTitle.innerHTML = data.title;
visionSubtitle.textContent = data.subtitle;
vision2030CardHeading.textContent = data.cardHeading;
vision2030CardText.textContent = data.cardText;
visionTitle.style.opacity = 1;
visionSubtitle.style.opacity = 1;
vision2030CardHeading.style.opacity = 1;
vision2030CardText.style.opacity = 1;
}, 200);
}
// Set transition styles for quick animations
[visionTitle, visionSubtitle, vision2030CardHeading, vision2030CardText].forEach(el => {
el.style.transition = 'opacity 0.25s ease';
});
altPill1.addEventListener('click', () => {
if (!altPill1.classList.contains('active')) {
applyAltTransition(alt1Data, altPill1, altPill2);
addSimLog('Toggled view to ALT 1: AI Pulse Layer model.', true);
}
});
altPill2.addEventListener('click', () => {
if (!altPill2.classList.contains('active')) {
applyAltTransition(alt2Data, altPill2, altPill1);
addSimLog('Toggled view to ALT 2: Neural Backbone architecture.', true);
}
});
/* ==========================================================================
4. TIMELINE HOVER SYNCRONIZATION
========================================================================== */
const roadmapCardsList = document.querySelectorAll('.roadmap-col-card');
const timelineDots = document.querySelectorAll('.node-dot-item');
roadmapCardsList.forEach((card, idx) => {
card.addEventListener('mouseenter', () => {
// Highlight the corresponding dot on timeline line
timelineDots.forEach(d => d.classList.remove('dot-hover'));
if (timelineDots[idx]) {
timelineDots[idx].classList.add('dot-hover');
// Temporarily expand scale in styling
timelineDots[idx].style.transform = 'translate(-50%, -50%) scale(1.5)';
timelineDots[idx].style.transition = 'transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1)';
}
});
card.addEventListener('mouseleave', () => {
if (timelineDots[idx]) {
timelineDots[idx].classList.remove('dot-hover');
timelineDots[idx].style.transform = 'translate(-50%, -50%) scale(1)';
}
});
});
/* ==========================================================================
5. HTML5 CANVAS: LIVE AI ROUTING SIMULATOR
========================================================================== */
const canvas = document.getElementById('simCanvas');
const ctx = canvas.getContext('2d');
// Controls
const toggleManualBtn = document.getElementById('toggle-manual');
const toggleAiBtn = document.getElementById('toggle-ai');
const speedBtn = document.getElementById('sim-speed-btn');
const refreshBtn = document.getElementById('sim-refresh-btn');
const riderCountSpan = document.getElementById('rider-count');
const consoleLogs = document.getElementById('sim-console');
// Metric DOM Handles
const simSlaVal = document.getElementById('sim-sla-val');
const simSlaDelta = document.getElementById('sim-sla-delta');
const simSlaProgress = document.getElementById('sim-sla-progress');
const simTimeVal = document.getElementById('sim-time-val');
const simTimeDelta = document.getElementById('sim-time-delta');
const simTimeProgress = document.getElementById('sim-time-progress');
const simCo2Val = document.getElementById('sim-co2-val');
const simCo2Delta = document.getElementById('sim-co2-delta');
const simCo2Progress = document.getElementById('sim-co2-progress');
// Simulation States
let isAiMode = false;
let animSpeed = 1; // Speed multiplier
let networkNodes = [];
let riders = [];
let lastTime = 0;
// Grid System Dimensions
function resizeCanvas() {
const dpr = window.devicePixelRatio || 1;
const rect = canvas.getBoundingClientRect();
canvas.width = rect.width * dpr;
canvas.height = rect.height * dpr;
ctx.scale(dpr, dpr);
}
resizeCanvas();
window.addEventListener('resize', resizeCanvas);
// Dynamic Log Handler
function addSimLog(message, isAI = false) {
const timeStr = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });
const logEntry = document.createElement('div');
logEntry.className = 'log-entry';
logEntry.innerHTML = `[${timeStr}] ${isAI ? '[MileTruth AI] ' : ''}${message}`;
consoleLogs.appendChild(logEntry);
consoleLogs.scrollTop = consoleLogs.scrollHeight;
// Keep maximum 8 log entries in terminal
if (consoleLogs.childElementCount > 8) {
consoleLogs.removeChild(consoleLogs.firstChild);
}
}
// Initialize Network Grid Nodes (Hyderabad Mock Grid)
function initNetworkGrid() {
networkNodes = [];
const width = canvas.width / (window.devicePixelRatio || 1);
const height = canvas.height / (window.devicePixelRatio || 1);
// Generate central hubs
const centralHub = { x: width * 0.5, y: height * 0.5, type: 'central', label: 'Central Hub EV' };
networkNodes.push(centralHub);
// Generate suburban delivery clusters
const clusterCount = 5;
const nodesPerCluster = 5;
for (let i = 0; i < clusterCount; i++) {
const angle = (i * Math.PI * 2) / clusterCount;
const dist = Math.min(width, height) * 0.3;
const cx = centralHub.x + Math.cos(angle) * dist;
const cy = centralHub.y + Math.sin(angle) * dist;
const clusterHub = { x: cx, y: cy, type: 'subhub', label: `Hub Zone ${String.fromCharCode(65 + i)}` };
networkNodes.push(clusterHub);
// Inner delivery terminal nodes
for (let j = 0; j < nodesPerCluster; j++) {
const subAngle = (j * Math.PI * 2) / nodesPerCluster;
const subDist = 35 + Math.random() * 25;
networkNodes.push({
x: cx + Math.cos(subAngle) * subDist,
y: cy + Math.sin(subAngle) * subDist,
type: 'delivery',
label: `Point ${i}-${j}`
});
}
}
// Spawn EV Rider particles
spawnRiders();
}
function spawnRiders() {
riders = [];
const hubNodes = networkNodes.filter(n => n.type === 'central' || n.type === 'subhub');
const deliveryNodes = networkNodes.filter(n => n.type === 'delivery');
const riderCount = 10;
riderCountSpan.textContent = `${riderCount} EVs`;
for (let i = 0; i < riderCount; i++) {
const startHub = hubNodes[Math.floor(Math.random() * hubNodes.length)];
const target = deliveryNodes[Math.floor(Math.random() * deliveryNodes.length)];
riders.push({
x: startHub.x,
y: startHub.y,
source: startHub,
target: target,
progress: Math.random(),
speed: 0.003 + Math.random() * 0.002,
id: `EV-${100 + i}`,
color: i % 2 === 0 ? 'rgba(255, 42, 95, 0.95)' : 'rgba(6, 182, 212, 0.95)'
});
}
}
// Grid rendering logic
function drawSimulationGrid() {
const width = canvas.width / (window.devicePixelRatio || 1);
const height = canvas.height / (window.devicePixelRatio || 1);
ctx.clearRect(0, 0, width, height);
// 1. Draw connecting arterial routes
ctx.strokeStyle = 'rgba(255, 255, 255, 0.025)';
ctx.lineWidth = 1;
const hubNodes = networkNodes.filter(n => n.type === 'central' || n.type === 'subhub');
ctx.beginPath();
for (let i = 0; i < hubNodes.length; i++) {
for (let j = i + 1; j < hubNodes.length; j++) {
ctx.moveTo(hubNodes[i].x, hubNodes[i].y);
ctx.lineTo(hubNodes[j].x, hubNodes[j].y);
}
}
ctx.stroke();
// 2. Draw active delivery paths
ctx.beginPath();
riders.forEach(rider => {
if (isAiMode) {
ctx.strokeStyle = 'rgba(255, 42, 95, 0.07)';
ctx.lineWidth = 2.5;
ctx.moveTo(rider.source.x, rider.source.y);
ctx.lineTo(rider.target.x, rider.target.y);
} else {
ctx.strokeStyle = 'rgba(156, 163, 175, 0.04)';
ctx.lineWidth = 1.5;
const midX = (rider.source.x + rider.target.x) / 2 + 50;
const midY = (rider.source.y + rider.target.y) / 2 - 50;
ctx.moveTo(rider.source.x, rider.source.y);
ctx.quadraticCurveTo(midX, midY, rider.target.x, rider.target.y);
}
});
ctx.stroke();
// 3. Draw grid node points
networkNodes.forEach(node => {
if (node.type === 'central') {
ctx.fillStyle = '#ff2a5f';
ctx.beginPath();
ctx.arc(node.x, node.y, 8, 0, Math.PI * 2);
ctx.fill();
ctx.strokeStyle = 'rgba(255, 42, 95, 0.2)';
ctx.lineWidth = 6;
ctx.stroke();
} else if (node.type === 'subhub') {
ctx.fillStyle = '#06b6d4';
ctx.beginPath();
ctx.arc(node.x, node.y, 5, 0, Math.PI * 2);
ctx.fill();
} else {
ctx.fillStyle = 'rgba(255, 255, 255, 0.12)';
ctx.beginPath();
ctx.arc(node.x, node.y, 2.5, 0, Math.PI * 2);
ctx.fill();
}
});
// 4. Animate EV Riders (Moving dots)
riders.forEach(rider => {
let riderX, riderY;
if (isAiMode) {
riderX = rider.source.x + (rider.target.x - rider.source.x) * rider.progress;
riderY = rider.source.y + (rider.target.y - rider.source.y) * rider.progress;
} else {
const t = rider.progress;
const midX = (rider.source.x + rider.target.x) / 2 + 50;
const midY = (rider.source.y + rider.target.y) / 2 - 50;
riderX = (1 - t) * (1 - t) * rider.source.x + 2 * (1 - t) * t * midX + t * t * rider.target.x;
riderY = (1 - t) * (1 - t) * rider.source.y + 2 * (1 - t) * t * midY + t * t * rider.target.y;
}
ctx.shadowBlur = 8;
ctx.shadowColor = rider.color;
ctx.fillStyle = rider.color;
ctx.beginPath();
ctx.arc(riderX, riderY, 4.5, 0, Math.PI * 2);
ctx.fill();
ctx.shadowBlur = 0;
const speedMultiplier = isAiMode ? 1.6 : 1.0;
rider.progress += rider.speed * animSpeed * speedMultiplier;
if (rider.progress >= 1.0) {
const deliveries = networkNodes.filter(n => n.type === 'delivery');
rider.source = rider.target;
rider.target = deliveries[Math.floor(Math.random() * deliveries.length)];
rider.progress = 0;
rider.speed = 0.003 + Math.random() * 0.002;
if (Math.random() > 0.6) {
if (isAiMode) {
addSimLog(`${rider.id} completed optimized route. SLA Locked.`, true);
} else {
addSimLog(`${rider.id} delivered package. Latency buffer +3.2s.`, false);
}
}
}
});
}
// Telemetry dashboard dynamic transitions
function updateMetricsDashboard() {
if (isAiMode) {
simSlaVal.textContent = '98.4%';
simSlaVal.style.color = 'var(--primary-glow)';
simSlaDelta.textContent = '+30.2% vs Manual';
simSlaDelta.className = 'delta';
simSlaProgress.style.width = '98.4%';
simSlaProgress.style.background = 'var(--primary)';
simTimeVal.textContent = '18.2 min';
simTimeVal.style.color = '#fff';
simTimeDelta.textContent = '-24.3 min threshold';
simTimeDelta.className = 'delta';
simTimeProgress.style.width = '24%';
simTimeProgress.style.background = 'var(--primary)';
simCo2Val.textContent = '340 kg';
simCo2Val.style.color = 'var(--accent-glow)';
simCo2Delta.textContent = '+183% baseline';
simCo2Progress.style.width = '92%';
} else {
simSlaVal.textContent = '68.2%';
simSlaVal.style.color = 'var(--text-secondary)';
simSlaDelta.textContent = '-30.2% vs AI';
simSlaDelta.className = 'delta negative';
simSlaProgress.style.width = '68.2%';
simSlaProgress.style.background = 'var(--text-muted)';
simTimeVal.textContent = '42.5 min';
simTimeVal.style.color = 'var(--text-secondary)';
simTimeDelta.textContent = '+24.3 min delayed';
simTimeDelta.className = 'delta negative';
simTimeProgress.style.width = '82%';
simTimeProgress.style.background = 'var(--text-muted)';
simCo2Val.textContent = '120 kg';
simCo2Val.style.color = 'var(--text-secondary)';
simCo2Delta.textContent = '+8% baseline';
simCo2Progress.style.width = '35%';
}
}
// Loop
function loop(timestamp) {
drawSimulationGrid();
requestAnimationFrame(loop);
}
// Click triggers
toggleManualBtn.addEventListener('click', () => {
if (isAiMode) {
isAiMode = false;
toggleAiBtn.classList.remove('active');
toggleManualBtn.classList.add('active');
addSimLog('Switched to unoptimized Manual Dispatch mode.');
updateMetricsDashboard();
}
});
toggleAiBtn.addEventListener('click', () => {
if (!isAiMode) {
isAiMode = true;
toggleManualBtn.classList.remove('active');
toggleAiBtn.classList.add('active');
addSimLog('MileTruth AI optimization activated. Resolving city bottlenecks...', true);
updateMetricsDashboard();
}
});
speedBtn.addEventListener('click', () => {
if (animSpeed === 1) {
animSpeed = 2.5;
speedBtn.style.color = 'var(--primary-glow)';
addSimLog('Boost mode active. Dispatch rate x2.5.');
} else {
animSpeed = 1;
speedBtn.style.color = 'var(--text-primary)';
addSimLog('Grid speed returned to normal.');
}
});
refreshBtn.addEventListener('click', () => {
initNetworkGrid();
addSimLog('Urban network grid re-routed and refreshed.');
});
// Start
initNetworkGrid();
requestAnimationFrame(loop);
});