Reorganize frontend into public/ with pages/ and js/ subdirectories

- public/index.html — landing page at root
- public/pages/ — all feature pages (regulations, loadboard, etc.)
- public/js/ — api.js, nav.js, mock data files
- All links updated to absolute paths (/pages/, /js/)
- Express static path updated to serve from public/
- Seed script path updated for new mock data location
- README updated with new project structure and setup guide
- Added .env.example template

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Daniel Kovalevich
2026-03-30 15:52:56 -04:00
parent f917fb8014
commit 93efb907ff
20 changed files with 281 additions and 109 deletions

448
public/js/api.js Normal file
View File

@@ -0,0 +1,448 @@
// =====================================================================
// PilotEdge API Client
// Fetches data from the backend API and transforms responses to match
// the shapes expected by the existing frontend rendering code.
// Replace mock-data.js and mock-data-extended.js with this file.
// =====================================================================
const API_BASE = '/api';
const PilotEdge = {
// Auth token management
_token: localStorage.getItem('pilotedge_token'),
setToken(token) {
this._token = token;
if (token) localStorage.setItem('pilotedge_token', token);
else localStorage.removeItem('pilotedge_token');
},
getToken() {
return this._token;
},
getUser() {
const raw = localStorage.getItem('pilotedge_user');
return raw ? JSON.parse(raw) : null;
},
setUser(user) {
if (user) localStorage.setItem('pilotedge_user', JSON.stringify(user));
else localStorage.removeItem('pilotedge_user');
},
// Core fetch wrapper
async request(path, options = {}) {
const headers = { 'Content-Type': 'application/json', ...options.headers };
if (this._token) headers['Authorization'] = `Bearer ${this._token}`;
const res = await fetch(`${API_BASE}${path}`, { ...options, headers });
if (!res.ok) {
const body = await res.json().catch(() => ({}));
const err = new Error(body.error || `API error ${res.status}`);
err.status = res.status;
throw err;
}
return res.json();
},
async get(path) { return this.request(path); },
async post(path, data) { return this.request(path, { method: 'POST', body: JSON.stringify(data) }); },
async put(path, data) { return this.request(path, { method: 'PUT', body: JSON.stringify(data) }); },
async del(path) { return this.request(path, { method: 'DELETE' }); },
// -----------------------------------------------------------------
// Auth
// -----------------------------------------------------------------
async register(email, password, name, role) {
const res = await this.post('/auth/register', { email, password, name, role });
this.setToken(res.token);
this.setUser(res.user);
return res;
},
async login(email, password) {
const res = await this.post('/auth/login', { email, password });
this.setToken(res.token);
this.setUser(res.user);
return res;
},
logout() {
this.setToken(null);
this.setUser(null);
},
async me() { return this.get('/auth/me'); },
// -----------------------------------------------------------------
// Regulations — returns MOCK_STATE_REGULATIONS-compatible shape
// -----------------------------------------------------------------
async getRegulations() {
const states = await this.get('/regulations');
return states.map(s => ({
name: s.name,
abbr: s.abbr,
lat: s.lat,
lng: s.lng,
permitWidth: s.regulation?.permitWidth || '',
permitHeight: s.regulation?.permitHeight || '',
permitLength: s.regulation?.permitLength || '',
permitWeight: s.regulation?.permitWeight || '',
escortWidth: s.regulation?.escortWidth || '',
escortHeight: s.regulation?.escortHeight || '',
escortLength: s.regulation?.escortLength || '',
escortWeight: s.regulation?.escortWeight || '',
travel: s.regulation?.travelRestrictions || '',
holidays: s.regulation?.holidays || '',
agency: s.regulation?.agency || '',
url: s.regulation?.url || '',
notes: s.regulation?.notes || '',
}));
},
// -----------------------------------------------------------------
// Equipment — returns MOCK_STATE_EQUIPMENT-compatible shape
// Object keyed by state abbr: { TX: { escort: {...}, carrier: {...} } }
// -----------------------------------------------------------------
async getEquipment() {
const states = await this.get('/regulations');
const equipment = {};
for (const s of states) {
if (!s.equipmentRequirements) {
const full = await this.get(`/regulations/${s.abbr}`);
s.equipmentRequirements = full.equipmentRequirements || [];
}
if (s.equipmentRequirements.length > 0) {
equipment[s.abbr] = {};
for (const eq of s.equipmentRequirements) {
const obj = {
certification: eq.certification || '',
vehicle: eq.vehicle || '',
signs: eq.signs || '',
lights: eq.lights || '',
heightPole: eq.heightPole || '',
flags: eq.flags || '',
communication: eq.communication || '',
safety: eq.safetyGear || '',
};
if (eq.type === 'escort') equipment[s.abbr].escort = obj;
else if (eq.type === 'carrier') {
// Parse carrier safetyGear back to individual fields
const gear = eq.safetyGear || '';
equipment[s.abbr].carrier = {
signs: eq.signs || '',
flags: eq.flags || '',
lights: eq.lights || '',
cones: extractGearField(gear, 'Cones'),
fireExtinguisher: extractGearField(gear, 'Fire ext'),
triangles: extractGearField(gear, 'Triangles'),
flares: extractGearField(gear, 'Flares'),
firstAid: extractGearField(gear, 'First aid'),
};
}
}
}
}
return equipment;
},
// -----------------------------------------------------------------
// Contacts — returns MOCK_STATE_CONTACTS-compatible shape
// Object keyed by state abbr: { AL: { name, permit, police, email, hours, portal } }
// -----------------------------------------------------------------
async getContacts() {
const contacts = await this.get('/contacts');
const result = {};
for (const c of contacts) {
result[c.state.abbr] = {
name: c.state.name,
permit: c.permitPhone,
police: c.policePhone,
email: c.email,
hours: c.hours,
portal: c.portalUrl,
};
}
return result;
},
// -----------------------------------------------------------------
// Calendar — returns MOCK_SEASONAL_RESTRICTIONS-compatible shape
// -----------------------------------------------------------------
async getSeasonalRestrictions() {
const restrictions = await this.get('/calendar');
return restrictions.map(r => ({
id: r.id,
state: r.state?.abbr || '',
stateName: r.state?.name || '',
type: r.type,
title: r.name,
startMonth: r.startMonth,
startDay: 1,
endMonth: r.endMonth,
endDay: 28,
description: r.description,
color: getRestrictionColor(r.type),
routes: '',
impact: '',
}));
},
// -----------------------------------------------------------------
// Truck Stops — returns MOCK_TRUCK_STOPS-compatible shape
// -----------------------------------------------------------------
async getTruckStops() {
const stops = await this.get('/truckstops');
return stops.map(ts => ({
id: ts.id,
name: ts.name,
type: 'truck_stop',
location: {
city: ts.address?.split(',')[0]?.trim() || '',
state: ts.state?.abbr || '',
lat: ts.lat,
lng: ts.lng,
},
oversizeFriendly: ts.hasOversizeParking,
entranceWidth: ts.entranceWidth || '',
entranceHeight: ts.entranceHeight || '',
lotSize: ts.lotSqFt ? `${ts.lotSqFt} sq ft` : '',
oversizeCapacity: '',
facilities: ts.facilities || [],
description: '',
comments: (ts.contributions || []).map(c => ({
user: c.user?.name || 'Anonymous',
date: c.createdAt,
text: c.content,
})),
}));
},
// -----------------------------------------------------------------
// Bridges — returns MOCK_BRIDGE_CLEARANCES-compatible shape
// -----------------------------------------------------------------
async getBridges() {
const bridges = await this.get('/bridges');
return bridges.map(b => ({
id: b.id,
route: b.route,
mileMarker: '',
type: b.name.split(' at ')[0] || 'Bridge',
location: {
desc: b.name.split(' at ')[1] || b.name,
city: '',
state: b.state?.abbr || '',
lat: b.lat,
lng: b.lng,
},
clearanceHeight: `${b.heightClearance}'`,
clearanceWidth: b.widthClearance ? `${b.widthClearance}'` : 'Unrestricted',
weightLimit: b.weightLimit ? `${b.weightLimit} lbs` : 'No posted limit',
notes: '',
}));
},
// -----------------------------------------------------------------
// Weigh Stations — returns MOCK_WEIGH_STATIONS-compatible shape
// -----------------------------------------------------------------
async getWeighStations() {
const stations = await this.get('/weighstations');
return stations.map(ws => ({
id: ws.id,
name: ws.name,
route: ws.route,
location: {
city: '',
state: ws.state?.abbr || '',
lat: ws.lat,
lng: ws.lng,
},
hours: ws.hours,
prePass: ws.prePass,
currentStatus: ws.currentStatus,
direction: ws.direction,
lastFlagged: ws.lastStatusUpdate || null,
flaggedBy: '',
notes: '',
}));
},
// -----------------------------------------------------------------
// Alerts — returns MOCK_ROUTE_CONDITIONS + MOCK_WEATHER_ALERTS shapes
// -----------------------------------------------------------------
async getAlerts() {
const alerts = await this.get('/alerts');
const routeConditions = [];
const weatherAlerts = [];
for (const a of alerts) {
if (a.type === 'weather' || a.type === 'wind') {
weatherAlerts.push({
id: a.id,
type: a.type,
severity: a.severity,
region: a.state?.name || '',
routes: a.route ? a.route.split(', ') : [],
description: a.description,
validFrom: a.startsAt,
validTo: a.endsAt,
source: 'NWS',
lat: 0,
lng: 0,
});
} else {
routeConditions.push({
id: a.id,
type: a.type,
severity: a.severity,
route: a.route,
location: {
desc: a.description.substring(0, 60),
state: a.state?.abbr || '',
lat: 0,
lng: 0,
},
description: a.description,
startDate: a.startsAt,
endDate: a.endsAt,
source: 'State DOT',
affectsOversize: true,
});
}
}
return { routeConditions, weatherAlerts };
},
// -----------------------------------------------------------------
// Load Board — returns MOCK_LOAD_BOARD-compatible shape
// -----------------------------------------------------------------
async getLoads() {
const data = await this.get('/loads?limit=100');
return (data.loads || []).map(l => ({
id: l.id,
carrier: l.poster?.name || 'Unknown',
origin: parseLocation(l.origin),
destination: parseLocation(l.destination),
departureDate: l.pickupDate,
dimensions: {
width: l.width,
height: l.height,
length: l.length,
weight: l.weight,
},
description: l.description,
escortsNeeded: l.escortsNeeded,
status: l.status,
postedDate: l.createdAt,
contact: l.poster?.name || '',
}));
},
// -----------------------------------------------------------------
// Escort Operators — returns MOCK_ESCORT_OPERATORS-compatible shape
// -----------------------------------------------------------------
async getEscortOperators() {
const escorts = await this.get('/escorts');
return escorts.map(e => ({
id: e.id,
name: e.user?.name || 'Unknown',
location: {
city: '',
state: '',
lat: e.lat,
lng: e.lng,
},
status: e.availability,
certifications: e.certifications || [],
vehicleType: e.vehicleType,
rating: e.rating,
totalJobs: e.ratingCount || 0,
experience: '',
contact: e.user?.email || '',
phone: e.phone,
bio: e.bio,
}));
},
// -----------------------------------------------------------------
// Documents — returns MOCK_DOCUMENTS-compatible shape
// -----------------------------------------------------------------
async getDocuments() {
try {
const docs = await this.get('/documents');
return docs.map(d => ({
id: d.id,
name: d.filename,
type: d.type,
state: '',
uploadDate: d.createdAt,
expiryDate: d.expiresAt,
fileSize: formatFileSize(d.sizeBytes),
status: d.expiresAt && new Date(d.expiresAt) < new Date() ? 'expired' : 'active',
}));
} catch (err) {
// If not authenticated, return empty array
if (err.status === 401) return [];
throw err;
}
},
// -----------------------------------------------------------------
// Orders
// -----------------------------------------------------------------
async submitOrder(orderData) {
return this.post('/orders', orderData);
},
async getOrders() {
return this.get('/orders');
},
// -----------------------------------------------------------------
// Contributions
// -----------------------------------------------------------------
async submitContribution(entityType, entityId, type, content) {
return this.post('/contributions', { entityType, entityId, type, content });
},
};
// -----------------------------------------------------------------
// Helper functions
// -----------------------------------------------------------------
function extractGearField(gear, label) {
const match = gear.match(new RegExp(`${label}:\\s*([^;]+)`));
return match ? match[1].trim() : '';
}
function getRestrictionColor(type) {
const colors = {
spring_weight: '#3b82f6',
winter_closure: '#8b5cf6',
harvest: '#f59e0b',
holiday_blackout: '#ef4444',
};
return colors[type] || '#6b7280';
}
function parseLocation(str) {
// Parse "City, ST" into { city, state, lat: 0, lng: 0 }
if (!str) return { city: '', state: '', lat: 0, lng: 0 };
const parts = str.split(',').map(s => s.trim());
return {
city: parts[0] || '',
state: parts[1] || '',
lat: 0,
lng: 0,
};
}
function formatFileSize(bytes) {
if (!bytes) return '0 B';
const units = ['B', 'KB', 'MB', 'GB'];
let i = 0;
let size = bytes;
while (size >= 1024 && i < units.length - 1) { size /= 1024; i++; }
return `${Math.round(size * 10) / 10} ${units[i]}`;
}

View File

@@ -0,0 +1,775 @@
// =====================================================================
// EXTENDED MOCK DATA — Additional modules for V1 POC
// All data is SIMULATED for demonstration purposes.
// Include AFTER mock-data.js: <script src="mock-data-extended.js">
// =====================================================================
// =====================================================================
// STATE DOT CONTACTS (Module 14)
// =====================================================================
const MOCK_STATE_CONTACTS = {
AL: { name:"Alabama", permit:"(334) 242-5100", police:"(800) 392-8800", email:"permits@aldot.example.gov", hours:"M-F 7am-5pm CT", portal:"https://www.dot.state.al.us/" },
AK: { name:"Alaska", permit:"(907) 365-1200", police:"(907) 269-5511", email:"permits@dot.alaska.example.gov", hours:"M-F 8am-4:30pm AKT", portal:"https://dot.alaska.gov/" },
AZ: { name:"Arizona", permit:"(602) 712-7355", police:"(602) 223-2000", email:"permits@azdot.example.gov", hours:"M-F 7am-5pm MST", portal:"https://azdot.gov/" },
AR: { name:"Arkansas", permit:"(501) 569-2381", police:"(501) 618-8000", email:"permits@ardot.example.gov", hours:"M-F 7am-4:30pm CT", portal:"https://www.ardot.gov/" },
CA: { name:"California", permit:"(916) 654-4849", police:"(800) 835-5247", email:"permits@caltrans.example.gov", hours:"M-F 8am-5pm PT", portal:"https://dot.ca.gov/" },
CO: { name:"Colorado", permit:"(303) 757-9539", police:"(303) 239-4501", email:"permits@cdot.example.gov", hours:"M-F 7am-5pm MT", portal:"https://www.codot.gov/" },
CT: { name:"Connecticut", permit:"(860) 594-2874", police:"(860) 685-8190", email:"permits@ct.example.gov", hours:"M-F 8am-4:30pm ET", portal:"https://portal.ct.gov/dot" },
DE: { name:"Delaware", permit:"(302) 326-4650", police:"(302) 739-5901", email:"permits@deldot.example.gov", hours:"M-F 8am-4pm ET", portal:"https://deldot.gov/" },
FL: { name:"Florida", permit:"(850) 410-5777", police:"(850) 617-2000", email:"permits@fdot.example.gov", hours:"M-F 7am-6pm ET", portal:"https://www.fdot.gov/" },
GA: { name:"Georgia", permit:"(404) 635-8040", police:"(404) 624-7000", email:"permits@dot.ga.example.gov", hours:"M-F 7:30am-4:30pm ET", portal:"https://www.dot.ga.gov/" },
HI: { name:"Hawaii", permit:"(808) 692-7675", police:"(808) 586-1352", email:"permits@hawaii.example.gov", hours:"M-F 7:45am-4:30pm HST", portal:"https://hidot.hawaii.gov/" },
ID: { name:"Idaho", permit:"(208) 334-8418", police:"(208) 884-7000", email:"permits@itd.example.gov", hours:"M-F 7am-5pm MT", portal:"https://itd.idaho.gov/" },
IL: { name:"Illinois", permit:"(217) 785-1477", police:"(217) 782-6637", email:"permits@idot.example.gov", hours:"M-F 7am-4:30pm CT", portal:"https://idot.illinois.gov/" },
IN: { name:"Indiana", permit:"(317) 615-7320", police:"(317) 232-8248", email:"permits@indot.example.gov", hours:"M-F 7:30am-4pm ET", portal:"https://www.in.gov/indot/" },
IA: { name:"Iowa", permit:"(515) 237-3264", police:"(515) 725-6090", email:"permits@iowadot.example.gov", hours:"M-F 7am-4:30pm CT", portal:"https://iowadot.gov/" },
KS: { name:"Kansas", permit:"(785) 296-3618", police:"(785) 296-6800", email:"permits@ksdot.example.gov", hours:"M-F 8am-5pm CT", portal:"https://www.ksdot.gov/" },
KY: { name:"Kentucky", permit:"(502) 564-4540", police:"(502) 227-8700", email:"permits@kytc.example.gov", hours:"M-F 8am-4:30pm ET", portal:"https://transportation.ky.gov/" },
LA: { name:"Louisiana", permit:"(225) 379-1436", police:"(225) 925-6006", email:"permits@dotd.la.example.gov", hours:"M-F 7:30am-4pm CT", portal:"https://www.dotd.la.gov/" },
ME: { name:"Maine", permit:"(207) 624-3600", police:"(207) 624-7076", email:"permits@maine.example.gov", hours:"M-F 8am-4pm ET", portal:"https://www.maine.gov/mdot/" },
MD: { name:"Maryland", permit:"(410) 582-5734", police:"(410) 486-3101", email:"permits@mdot.example.gov", hours:"M-F 8am-4:30pm ET", portal:"https://www.roads.maryland.gov/" },
MA: { name:"Massachusetts", permit:"(857) 368-9640", police:"(508) 820-2300", email:"permits@massdot.example.gov", hours:"M-F 8:30am-5pm ET", portal:"https://www.mass.gov/massdot" },
MI: { name:"Michigan", permit:"(517) 335-0945", police:"(517) 332-2521", email:"permits@michigan.example.gov", hours:"M-F 8am-4:30pm ET", portal:"https://www.michigan.gov/mdot" },
MN: { name:"Minnesota", permit:"(651) 296-6000", police:"(651) 201-7100", email:"permits@mndot.example.gov", hours:"M-F 7:30am-4pm CT", portal:"https://www.dot.state.mn.us/" },
MS: { name:"Mississippi", permit:"(601) 359-7685", police:"(601) 987-1212", email:"permits@mdot.ms.example.gov", hours:"M-F 7am-5pm CT", portal:"https://mdot.ms.gov/" },
MO: { name:"Missouri", permit:"(573) 751-7100", police:"(573) 751-3313", email:"permits@modot.example.gov", hours:"M-F 7:30am-4:30pm CT", portal:"https://www.modot.org/" },
MT: { name:"Montana", permit:"(406) 444-6130", police:"(406) 444-3780", email:"permits@mdt.example.gov", hours:"M-F 8am-5pm MT", portal:"https://www.mdt.mt.gov/" },
NE: { name:"Nebraska", permit:"(402) 471-0034", police:"(402) 471-4545", email:"permits@dot.ne.example.gov", hours:"M-F 8am-5pm CT", portal:"https://dot.nebraska.gov/" },
NV: { name:"Nevada", permit:"(775) 888-7410", police:"(775) 687-5300", email:"permits@dot.nv.example.gov", hours:"M-F 7am-5pm PT", portal:"https://www.dot.nv.gov/" },
NH: { name:"New Hampshire", permit:"(603) 227-6100", police:"(603) 223-4381", email:"permits@nh.example.gov", hours:"M-F 8am-4pm ET", portal:"https://www.nh.gov/dot/" },
NJ: { name:"New Jersey", permit:"(609) 530-2345", police:"(609) 882-2000", email:"permits@njdot.example.gov", hours:"M-F 8am-4:30pm ET", portal:"https://www.nj.gov/transportation/" },
NM: { name:"New Mexico", permit:"(505) 827-4565", police:"(505) 827-9300", email:"permits@dot.nm.example.gov", hours:"M-F 8am-5pm MT", portal:"https://www.dot.nm.gov/" },
NY: { name:"New York", permit:"(518) 457-1014", police:"(518) 457-6811", email:"permits@nysdot.example.gov", hours:"M-F 8am-4pm ET", portal:"https://www.dot.ny.gov/" },
NC: { name:"North Carolina", permit:"(919) 733-7752", police:"(919) 733-7952", email:"permits@ncdot.example.gov", hours:"M-F 8am-5pm ET", portal:"https://www.ncdot.gov/" },
ND: { name:"North Dakota", permit:"(701) 328-2543", police:"(701) 328-2455", email:"permits@dot.nd.example.gov", hours:"M-F 8am-5pm CT", portal:"https://www.dot.nd.gov/" },
OH: { name:"Ohio", permit:"(614) 351-2300", police:"(614) 466-2660", email:"permits@odot.example.gov", hours:"M-F 7am-5pm ET", portal:"https://www.transportation.ohio.gov/" },
OK: { name:"Oklahoma", permit:"(405) 521-2558", police:"(405) 425-2424", email:"permits@odot.ok.example.gov", hours:"M-F 7:30am-4:30pm CT", portal:"https://oklahoma.gov/odot.html" },
OR: { name:"Oregon", permit:"(503) 378-6699", police:"(503) 378-3720", email:"permits@odot.or.example.gov", hours:"M-F 7:30am-4:30pm PT", portal:"https://www.oregon.gov/odot/" },
PA: { name:"Pennsylvania", permit:"(717) 787-3156", police:"(717) 783-5599", email:"permits@penndot.example.gov", hours:"M-F 8am-4pm ET", portal:"https://www.penndot.pa.gov/" },
RI: { name:"Rhode Island", permit:"(401) 222-2481", police:"(401) 444-1000", email:"permits@ridot.example.gov", hours:"M-F 8:30am-4pm ET", portal:"https://www.dot.ri.gov/" },
SC: { name:"South Carolina", permit:"(803) 737-1290", police:"(803) 896-7920", email:"permits@scdot.example.gov", hours:"M-F 8am-5pm ET", portal:"https://www.scdot.org/" },
SD: { name:"South Dakota", permit:"(605) 773-3571", police:"(605) 773-3105", email:"permits@sddot.example.gov", hours:"M-F 8am-5pm CT", portal:"https://dot.sd.gov/" },
TN: { name:"Tennessee", permit:"(615) 741-3821", police:"(615) 251-5175", email:"permits@tn.example.gov", hours:"M-F 7am-4:30pm CT", portal:"https://www.tn.gov/tdot.html" },
TX: { name:"Texas", permit:"(512) 465-7603", police:"(512) 424-2000", email:"permits@txdmv.example.gov", hours:"M-F 7am-6pm CT", portal:"https://www.txdmv.gov/" },
UT: { name:"Utah", permit:"(801) 965-4468", police:"(801) 887-3800", email:"permits@udot.example.gov", hours:"M-F 8am-5pm MT", portal:"https://www.udot.utah.gov/" },
VT: { name:"Vermont", permit:"(802) 828-2070", police:"(802) 244-8727", email:"permits@vtrans.example.gov", hours:"M-F 7:45am-4:30pm ET", portal:"https://vtrans.vermont.gov/" },
VA: { name:"Virginia", permit:"(804) 497-1560", police:"(804) 674-2000", email:"permits@vdot.example.gov", hours:"M-F 8am-5pm ET", portal:"https://www.virginiadot.org/" },
WA: { name:"Washington", permit:"(360) 704-6340", police:"(360) 596-4000", email:"permits@wsdot.example.gov", hours:"M-F 7am-5pm PT", portal:"https://wsdot.wa.gov/" },
WV: { name:"West Virginia", permit:"(304) 558-3063", police:"(304) 746-2100", email:"permits@wvdoh.example.gov", hours:"M-F 7am-4pm ET", portal:"https://transportation.wv.gov/" },
WI: { name:"Wisconsin", permit:"(608) 266-7320", police:"(608) 266-3212", email:"permits@wisdot.example.gov", hours:"M-F 7am-4:30pm CT", portal:"https://wisconsindot.gov/" },
WY: { name:"Wyoming", permit:"(307) 777-4375", police:"(307) 777-4301", email:"permits@wydot.example.gov", hours:"M-F 8am-5pm MT", portal:"https://www.dot.state.wy.us/" },
DC: { name:"District of Columbia", permit:"(202) 673-6813", police:"(202) 727-9099", email:"permits@ddot.example.gov", hours:"M-F 8:30am-4:30pm ET", portal:"https://ddot.dc.gov/" }
};
// =====================================================================
// STATE EQUIPMENT REQUIREMENTS (Module 12)
// Detailed data for major trucking states; others show "Data coming soon"
// =====================================================================
const MOCK_STATE_EQUIPMENT = {
TX: {
escort: {
certification: "Required — must complete TxDMV-approved pilot/escort vehicle course",
vehicle: "Passenger car, pickup, or SUV — no commercial vehicles",
signs: "OVERSIZE LOAD sign, minimum 7' wide × 18\" tall, yellow background, black letters, front and rear",
lights: "2 amber rotating or strobe lights mounted on roof, visible from 500'",
heightPole: "Required when leading overheight loads exceeding 15'",
flags: "18\" red/orange fluorescent flags at 4 corners of vehicle",
communication: "CB radio required — channel 19 monitored at all times",
safety: "First aid kit, 10BC fire extinguisher, flashlight, reflective vest"
},
carrier: {
signs: "OVERSIZE LOAD banner — roof-mounted or bumper-mounted permitted, yellow/black, min 7'×18\"",
flags: "18\" red/orange flags at each corner and extremity of load",
lights: "Amber flashing lights at widest points of load, front and rear",
cones: "Not required by state, but recommended",
fireExtinguisher: "10BC rated fire extinguisher required",
triangles: "3 reflective triangles required",
flares: "Not required",
firstAid: "Not required by state"
}
},
CA: {
escort: {
certification: "Required — CHP-approved Pilot Car Escort Training (PCET) certification",
vehicle: "Must pass annual CHP inspection — car, pickup, or SUV",
signs: "OVERSIZE LOAD sign front and rear, min 6' wide × 18\" tall, reflective",
lights: "Amber flashing light on roof, visible 360°",
heightPole: "Required for all overheight loads — must extend to load height plus 6\"",
flags: "Red/orange fluorescent flags, 18\" min, at 4 corners",
communication: "Two-way radio or CB required",
safety: "First aid kit, fire extinguisher, 3 reflective triangles, reflective vest, flashlight"
},
carrier: {
signs: "OVERSIZE LOAD banner — ROOF-MOUNTED REQUIRED, reflective, min 7'×18\"",
flags: "Red/orange flags at extremities, 18\" min — required day and night",
lights: "Amber warning lights at widest points, amber flashers on truck",
cones: "6 traffic cones required (28\" min height)",
fireExtinguisher: "10BC rated required",
triangles: "3 reflective triangles required",
flares: "3 fuses/flares required",
firstAid: "First aid kit required"
}
},
OH: {
escort: {
certification: "Not state-mandated, but ODOT recommends completion of training course",
vehicle: "Passenger vehicle or light-duty truck",
signs: "OVERSIZE LOAD sign, yellow/black, min 5' wide × 10\" tall",
lights: "Amber rotating or flashing light on roof",
heightPole: "Required when escorting overheight loads",
flags: "Orange flags at corners of vehicle",
communication: "CB radio recommended, cell phone minimum",
safety: "Fire extinguisher, first aid kit recommended"
},
carrier: {
signs: "OVERSIZE LOAD banner — bumper-mounted permitted, min 7'×18\"",
flags: "Red/orange flags at extremities of load",
lights: "Amber flashing lights on widest points of load",
cones: "Not required",
fireExtinguisher: "Required",
triangles: "3 reflective triangles required",
flares: "Not required",
firstAid: "Not required"
}
},
PA: {
escort: {
certification: "Required — PennDOT approved training course",
vehicle: "Single-unit vehicle, must be registered and insured",
signs: "OVERSIZE LOAD sign, yellow/black, front and rear",
lights: "Amber 360° flashing/rotating light on roof, visible 500'",
heightPole: "Required for overheight loads on Turnpike; recommended elsewhere",
flags: "Red/orange flags at 4 corners",
communication: "CB radio required",
safety: "First aid kit, fire extinguisher, reflective vest, flashlight"
},
carrier: {
signs: "OVERSIZE LOAD sign — front and rear of vehicle, roof-mounted on tractor",
flags: "Red/orange fluorescent flags at extremities and corners of load",
lights: "Amber rotating light on cab, amber lights at widest points",
cones: "Not required",
fireExtinguisher: "10BC rated required",
triangles: "3 reflective triangles required",
flares: "Not required",
firstAid: "Not required"
}
},
FL: {
escort: {
certification: "Not state-mandated — no formal certification program",
vehicle: "Any passenger vehicle or light truck",
signs: "OVERSIZE LOAD sign, yellow/black, displayed prominently",
lights: "Amber rotating or strobe light on roof",
heightPole: "Required for overheight loads when escort is in front",
flags: "Red/orange flags at corners of escort vehicle",
communication: "CB radio or two-way radio required",
safety: "Fire extinguisher recommended, first aid kit recommended"
},
carrier: {
signs: "OVERSIZE LOAD banner — bumper-mounted or roof-mounted, min 7'×18\"",
flags: "18\" red/orange flags at each extremity of load",
lights: "Amber warning lights at widest points",
cones: "Not required",
fireExtinguisher: "Required",
triangles: "3 reflective triangles required",
flares: "Not required",
firstAid: "Not required"
}
},
GA: {
escort: {
certification: "Not state-mandated — training recommended",
vehicle: "Passenger vehicle or light-duty truck",
signs: "OVERSIZE LOAD sign front and rear",
lights: "Amber flashing or rotating light, roof-mounted",
heightPole: "Required for overheight loads",
flags: "Red/orange flags at corners",
communication: "CB radio or cell phone",
safety: "Fire extinguisher, first aid kit"
},
carrier: {
signs: "OVERSIZE LOAD banner — bumper-mounted permitted",
flags: "Red/orange flags at extremities",
lights: "Amber flashers at widest points",
cones: "Not required",
fireExtinguisher: "Required",
triangles: "3 triangles required",
flares: "Not required",
firstAid: "Not required"
}
},
IL: {
escort: {
certification: "Not state-mandated",
vehicle: "Single-unit passenger vehicle",
signs: "OVERSIZE LOAD sign, front and rear, yellow/black",
lights: "Amber rotating light on roof",
heightPole: "Required for overheight escorts",
flags: "Red/orange flags at 4 corners",
communication: "CB radio required for loads over 14' wide",
safety: "Fire extinguisher, reflective vest"
},
carrier: {
signs: "OVERSIZE LOAD banner — front and rear, roof or bumper mount allowed",
flags: "Red/orange flags at load extremities and corners, 18\" min",
lights: "Amber flashers on widest points, rotating amber on cab",
cones: "Not required",
fireExtinguisher: "Required",
triangles: "3 reflective triangles required",
flares: "Not required",
firstAid: "Not required"
}
},
NY: {
escort: {
certification: "Required — NYSDOT approved escort vehicle operator course",
vehicle: "Passenger vehicle, under 10,000 lbs GVW",
signs: "OVERSIZE LOAD sign front and rear, black on yellow, reflective",
lights: "Amber 360° light, roof-mounted, visible 500'",
heightPole: "Required for all overheight loads in the state",
flags: "18\" red/orange flags at all 4 corners",
communication: "CB radio required, cell phone as backup",
safety: "First aid kit, fire extinguisher, 3 reflective triangles, reflective vest"
},
carrier: {
signs: "OVERSIZE LOAD sign — ROOF-MOUNTED REQUIRED on tractor",
flags: "Red/orange flags at all corners and extremities, 18\" min",
lights: "Amber rotating on cab, amber flashers at widest points of load",
cones: "Not required",
fireExtinguisher: "10BC required",
triangles: "3 reflective triangles required",
flares: "3 fusees required",
firstAid: "Not required"
}
},
NC: {
escort: {
certification: "Not state-mandated — recommended",
vehicle: "Passenger vehicle or light truck",
signs: "OVERSIZE LOAD sign front and rear",
lights: "Amber rotating/flashing on roof",
heightPole: "Required for overheight loads",
flags: "Red/orange flags at corners",
communication: "CB radio recommended",
safety: "Fire extinguisher, first aid kit recommended"
},
carrier: {
signs: "OVERSIZE LOAD banner — bumper-mounted permitted",
flags: "Red/orange flags at extremities",
lights: "Amber flashers at widest points",
cones: "Not required",
fireExtinguisher: "Required",
triangles: "3 required",
flares: "Not required",
firstAid: "Not required"
}
},
LA: {
escort: {
certification: "Not state-mandated",
vehicle: "Passenger vehicle or light truck",
signs: "OVERSIZE LOAD sign, front and rear, yellow/black",
lights: "Amber rotating light on roof",
heightPole: "Required for overheight loads exceeding 14'6\"",
flags: "Red/orange flags at all corners",
communication: "CB radio required",
safety: "Fire extinguisher, first aid kit"
},
carrier: {
signs: "OVERSIZE LOAD banner — bumper or roof mount",
flags: "Red/orange flags at extremities, 18\" min",
lights: "Amber warning lights at widest points",
cones: "Not required",
fireExtinguisher: "Required",
triangles: "3 required",
flares: "Not required",
firstAid: "Not required"
}
},
OK: {
escort: {
certification: "Not state-mandated",
vehicle: "Passenger vehicle or pickup truck",
signs: "OVERSIZE LOAD sign, yellow/black, front and rear",
lights: "Amber rotating or strobe on roof",
heightPole: "Required for overheight loads",
flags: "Red/orange flags at 4 corners",
communication: "CB radio required",
safety: "Fire extinguisher, flashlight"
},
carrier: {
signs: "OVERSIZE LOAD banner — bumper-mounted or roof-mounted accepted",
flags: "Red/orange flags at all corners and extremities",
lights: "Amber flashers at widest/tallest/longest points",
cones: "Not required",
fireExtinguisher: "Required",
triangles: "3 reflective triangles required",
flares: "Not required",
firstAid: "Not required"
}
},
IN: {
escort: {
certification: "Not state-mandated — INDOT recommends training",
vehicle: "Passenger vehicle or light truck",
signs: "OVERSIZE LOAD sign, front and rear",
lights: "Amber rotating/flashing light on roof",
heightPole: "Required for overheight loads",
flags: "Orange flags at corners",
communication: "CB radio or cell phone",
safety: "Fire extinguisher recommended"
},
carrier: {
signs: "OVERSIZE LOAD banner — front and rear, bumper mount OK",
flags: "Red/orange flags at extremities",
lights: "Amber flashers at widest points",
cones: "Not required",
fireExtinguisher: "Required",
triangles: "3 required",
flares: "Not required",
firstAid: "Not required"
}
}
};
// =====================================================================
// TRUCK STOPS & PARKING (Module 5)
// =====================================================================
const MOCK_TRUCK_STOPS = [
{
id:"TS-001", name:"Sapp Bros. Travel Center", type:"truck_stop",
location:{ city:"Amarillo", state:"TX", lat:35.19, lng:-101.78 },
oversizeFriendly:true, entranceWidth:"26'", entranceHeight:"No restriction",
lotSize:"4.2 acres total", oversizeCapacity:"5-6 oversize loads",
facilities:["fuel","food","restrooms","showers","mechanic","scale"],
description:"Large open lot on the south side. Adjacent gravel area can fit extra-wide loads. South entrance is best for oversize.",
comments:[
{ user:"TruckerMike_TX", date:"2026-03-15", text:"Parked a 16'4\" wide wind blade here. South lot had plenty of room. Use the south entrance off the service road." },
{ user:"HighPolePete", date:"2026-02-28", text:"South entrance is the only one that works for oversize. North has tight posts. Good fuel prices." }
]
},
{
id:"TS-002", name:"Iowa 80 Truckstop", type:"truck_stop",
location:{ city:"Walcott", state:"IA", lat:41.58, lng:-90.77 },
oversizeFriendly:true, entranceWidth:"30'+", entranceHeight:"No restriction",
lotSize:"8+ acres total", oversizeCapacity:"10+ oversize loads",
facilities:["fuel","food","restrooms","showers","mechanic","scale","trucking_museum","barber","chiropractor"],
description:"World's largest truck stop. Massive open lot on east side regularly used for oversize staging. Multiple wide entrances.",
comments:[
{ user:"MidwestHauler", date:"2026-03-20", text:"Best oversize parking on I-80. East lot is huge — I've seen 3 blade trucks staged here at once." },
{ user:"BladRunner_IA", date:"2026-03-05", text:"Great staging area for wind energy loads heading south on I-80 to I-35." }
]
},
{
id:"TS-003", name:"Petro Stopping Center", type:"truck_stop",
location:{ city:"Rochelle", state:"IL", lat:41.92, lng:-89.07 },
oversizeFriendly:true, entranceWidth:"24'", entranceHeight:"No restriction",
lotSize:"3.8 acres", oversizeCapacity:"3-4 oversize loads",
facilities:["fuel","food","restrooms","showers","iron_skillet"],
description:"I-39/I-88 junction location. Open area behind main lot can accommodate oversized loads. Wind blade traffic common.",
comments:[
{ user:"PrairiePilot", date:"2026-03-10", text:"Regular stop for blade loads on I-39 corridor. Back lot is gravel but solid ground." }
]
},
{
id:"TS-004", name:"Breezewood Travel Plaza", type:"rest_area",
location:{ city:"Breezewood", state:"PA", lat:39.99, lng:-78.24 },
oversizeFriendly:false, entranceWidth:"14'", entranceHeight:"13'8\" (canopy)",
lotSize:"2 acres", oversizeCapacity:"1-2 standard oversize only",
facilities:["fuel","food","restrooms"],
description:"Famous I-70/I-76 interchange. Very tight for oversize — canopy restricts height. NOT recommended for wide or tall loads.",
comments:[
{ user:"KeystoneEscort", date:"2026-03-22", text:"DO NOT bring oversize through the main fuel canopy. There's a pull-off east of the plaza on the service road that works in a pinch." },
{ user:"NE_Hauler", date:"2026-02-15", text:"Avoid this place with anything over 12' wide. The whole town is a bottleneck. Plan to fuel before or after." }
]
},
{
id:"TS-005", name:"Buc-ee's", type:"truck_stop",
location:{ city:"Terrell", state:"TX", lat:32.72, lng:-96.22 },
oversizeFriendly:true, entranceWidth:"28'", entranceHeight:"No restriction",
lotSize:"5+ acres", oversizeCapacity:"4-5 oversize loads",
facilities:["fuel","food","restrooms","ev_charging"],
description:"Massive lot with wide lanes. Oversize can park on the outer perimeter. No dedicated truck parking but plenty of space.",
comments:[
{ user:"LoneStarOS", date:"2026-03-18", text:"Clean restrooms and great food. Park on the far east side — wide open and easy in/out." }
]
},
{
id:"TS-006", name:"Pilot Travel Center", type:"truck_stop",
location:{ city:"Salina", state:"KS", lat:38.81, lng:-97.59 },
oversizeFriendly:true, entranceWidth:"24'", entranceHeight:"No restriction",
lotSize:"3.5 acres", oversizeCapacity:"3-4 oversize loads",
facilities:["fuel","food","restrooms","showers","scale"],
description:"I-70/I-135 junction. Good oversize parking behind the main lot. Flat gravel area to the south.",
comments:[
{ user:"KSWindHauler", date:"2026-03-12", text:"Solid mid-Kansas stop. South gravel lot handles blade trucks fine." }
]
},
{
id:"TS-007", name:"Little America Travel Center", type:"truck_stop",
location:{ city:"Little America", state:"WY", lat:41.54, lng:-110.07 },
oversizeFriendly:true, entranceWidth:"30'+", entranceHeight:"No restriction",
lotSize:"6 acres", oversizeCapacity:"6-8 oversize loads",
facilities:["fuel","food","restrooms","hotel","showers"],
description:"Remote I-80 oasis with enormous lot. Very oversize-friendly — wide open spaces. Common staging point for loads heading through Wyoming.",
comments:[
{ user:"RockyMtnLog", date:"2026-03-08", text:"Best oversize stop in southern Wyoming. Huge lot, 24/7 fuel. Wind can be brutal though — check conditions before stopping." },
{ user:"WYO_Escort", date:"2026-02-20", text:"We stage here all the time for loads heading east or west on I-80. Hotel is decent for overnight." }
]
},
{
id:"TS-008", name:"Bosselman Travel Center", type:"truck_stop",
location:{ city:"North Platte", state:"NE", lat:41.11, lng:-100.77 },
oversizeFriendly:true, entranceWidth:"24'", entranceHeight:"No restriction",
lotSize:"3 acres", oversizeCapacity:"3-4 oversize loads",
facilities:["fuel","food","restrooms","showers","mechanic"],
description:"I-80 corridor stop. Open area north of main lot usable for oversize. Regular wind turbine traffic.",
comments:[
{ user:"NE_OversizeOps", date:"2026-03-01", text:"Good stop on the I-80 wind corridor. North lot is gravel and fits wide loads." }
]
},
{
id:"TS-009", name:"Flying J Travel Center", type:"truck_stop",
location:{ city:"Dillon", state:"SC", lat:34.41, lng:-79.39 },
oversizeFriendly:true, entranceWidth:"22'", entranceHeight:"No restriction",
lotSize:"3.2 acres", oversizeCapacity:"2-3 oversize loads",
facilities:["fuel","food","restrooms","showers","scale"],
description:"I-95/I-20 junction. Some oversize parking on the east side. Gets busy — arrive early.",
comments:[
{ user:"PeachStateP", date:"2026-03-14", text:"East side has room for 2-3 oversize rigs. Tight during peak hours though." }
]
},
{
id:"TS-010", name:"Love's Travel Stop", type:"truck_stop",
location:{ city:"Eloy", state:"AZ", lat:32.74, lng:-111.54 },
oversizeFriendly:true, entranceWidth:"26'", entranceHeight:"No restriction",
lotSize:"4 acres", oversizeCapacity:"4-5 oversize loads",
facilities:["fuel","food","restrooms","showers"],
description:"I-10 corridor between Phoenix and Tucson. Open desert lot on south side handles oversize well.",
comments:[
{ user:"DesertSun_TX", date:"2026-03-25", text:"Good I-10 stop. South lot is flat and open. Carry extra water — it's the desert." }
]
}
];
// =====================================================================
// BRIDGE & OVERPASS CLEARANCES (Module 6)
// =====================================================================
const MOCK_BRIDGE_CLEARANCES = [
{ id:"BR-001", route:"I-95 NB", mileMarker:"67.2", type:"Overpass",
location:{ desc:"Fort McHenry Tunnel approach", city:"Baltimore", state:"MD", lat:39.26, lng:-76.58 },
clearanceHeight:"13'6\"", clearanceWidth:"No restriction", weightLimit:"80,000 lbs (standard)",
notes:"Major bottleneck for overheight loads on I-95 NB. Overheight loads must use I-695 bypass around Baltimore." },
{ id:"BR-002", route:"I-70 WB", mileMarker:"213.5", type:"Tunnel",
location:{ desc:"Eisenhower-Johnson Memorial Tunnel", city:"Silver Plume", state:"CO", lat:39.68, lng:-105.91 },
clearanceHeight:"13'11\"", clearanceWidth:"13'0\" (per lane)", weightLimit:"Route-specific",
notes:"Highest point on the Interstate system. Oversize loads often must use US-6 Loveland Pass detour. Hazmat prohibited." },
{ id:"BR-003", route:"I-64 WB", mileMarker:"58.1", type:"Tunnel",
location:{ desc:"East River Mountain Tunnel", city:"Near Bluefield", state:"WV", lat:37.37, lng:-81.10 },
clearanceHeight:"15'5\"", clearanceWidth:"12'0\" (per lane)", weightLimit:"80,000 lbs",
notes:"Two-lane bore with restricted width. Overwide loads must use alternate routes. Frequent delays." },
{ id:"BR-004", route:"I-35 SB", mileMarker:"429.8", type:"Overpass",
location:{ desc:"Downtown Dallas interchange", city:"Dallas", state:"TX", lat:32.79, lng:-96.80 },
clearanceHeight:"14'0\"", clearanceWidth:"No restriction", weightLimit:"Standard",
notes:"Several low overpasses through downtown Dallas on I-35E. Overheight loads should use I-35W bypass through Fort Worth." },
{ id:"BR-005", route:"I-76 EB", mileMarker:"161.3", type:"Overpass",
location:{ desc:"Pennsylvania Turnpike — Valley Forge area", city:"King of Prussia", state:"PA", lat:40.09, lng:-75.38 },
clearanceHeight:"14'2\"", clearanceWidth:"No restriction", weightLimit:"Turnpike limits apply",
notes:"PA Turnpike has numerous older overpasses with restricted clearances. Contact Turnpike Commission for oversize routing." },
{ id:"BR-006", route:"US-20 EB", mileMarker:"N/A", type:"Overpass (multiple)",
location:{ desc:"Route 20 through Connecticut", city:"Various", state:"CT", lat:41.60, lng:-72.75 },
clearanceHeight:"12'6\" — 13'6\" (varies)", clearanceWidth:"Restricted at several points", weightLimit:"Varies by bridge",
notes:"Multiple low clearance overpasses along US-20 through CT. Not recommended for overheight. Use I-84 or I-91 where possible." },
{ id:"BR-007", route:"I-90 WB", mileMarker:"52.4", type:"Overpass",
location:{ desc:"Chicago Skyway / Dan Ryan interchange", city:"Chicago", state:"IL", lat:41.72, lng:-87.56 },
clearanceHeight:"14'0\"", clearanceWidth:"No restriction", weightLimit:"Standard",
notes:"Chicago metro area has multiple low overpasses. Oversize loads require IDOT-approved routing through the metro." },
{ id:"BR-008", route:"I-24 EB", mileMarker:"174.9", type:"Overpass",
location:{ desc:"Chattanooga downtown area", city:"Chattanooga", state:"TN", lat:35.04, lng:-85.28 },
clearanceHeight:"14'4\"", clearanceWidth:"No restriction", weightLimit:"Standard",
notes:"Series of overpasses through downtown Chattanooga with varying clearances. Check permit routing carefully." },
{ id:"BR-009", route:"I-10 EB", mileMarker:"768.3", type:"Overpass",
location:{ desc:"Houston ship channel bridge approaches", city:"Houston", state:"TX", lat:29.74, lng:-95.09 },
clearanceHeight:"Varies — 14'6\" to 16'2\"", clearanceWidth:"No restriction", weightLimit:"Standard",
notes:"Complex interchange area with varying clearances. Follow permitted route exactly. Some ramps have lower clearances than mainline." },
{ id:"BR-010", route:"I-81 SB", mileMarker:"300.1", type:"Overpass",
location:{ desc:"Harrisburg area", city:"Harrisburg", state:"PA", lat:40.28, lng:-76.87 },
clearanceHeight:"14'6\"", clearanceWidth:"No restriction", weightLimit:"Standard",
notes:"Several overpasses in the Harrisburg metro with clearances between 14' and 15'. Common corridor for northeast oversize traffic." }
];
// =====================================================================
// WEIGH STATIONS (Module 13)
// =====================================================================
const MOCK_WEIGH_STATIONS = [
{ id:"WS-001", name:"Hillsboro Weigh Station", route:"I-35 NB",
location:{ city:"Hillsboro", state:"TX", lat:31.98, lng:-97.13 },
hours:"24/7", prePass:true,
currentStatus:"open", lastFlagged:"2026-03-29T14:30:00Z", flaggedBy:"TruckerJoe42",
notes:"Oversize loads almost always pulled in for inspection. Have permits readily accessible." },
{ id:"WS-002", name:"Ehrenberg Port of Entry", route:"I-10 WB",
location:{ city:"Ehrenberg", state:"AZ", lat:33.60, lng:-114.52 },
hours:"24/7", prePass:true,
currentStatus:"open", lastFlagged:"2026-03-29T11:00:00Z", flaggedBy:"DesertSun",
notes:"California/Arizona border checkpoint. All oversize must stop. Can have long lines during morning hours." },
{ id:"WS-003", name:"Darien Weigh Station", route:"I-95 NB",
location:{ city:"Darien", state:"GA", lat:31.38, lng:-81.44 },
hours:"6am-10pm", prePass:true,
currentStatus:"open", lastFlagged:"2026-03-29T09:15:00Z", flaggedBy:"SE_Hauler",
notes:"Florida/Georgia border area. Oversize permits checked regularly." },
{ id:"WS-004", name:"Upton Weigh Station", route:"I-80 EB",
location:{ city:"Upton", state:"WY", lat:41.00, lng:-104.62 },
hours:"24/7", prePass:false,
currentStatus:"closed", lastFlagged:"2026-03-29T16:45:00Z", flaggedBy:"WYO_Escort",
notes:"Wyoming/Nebraska border area. All commercial traffic must stop when open. Wind closures may affect station hours." },
{ id:"WS-005", name:"Moriarty Port of Entry", route:"I-40 EB",
location:{ city:"Moriarty", state:"NM", lat:34.99, lng:-106.05 },
hours:"24/7", prePass:true,
currentStatus:"open", lastFlagged:"2026-03-29T10:30:00Z", flaggedBy:"SW_Oversize",
notes:"East of Albuquerque. All commercial vehicles must report. Oversize permits verified." },
{ id:"WS-006", name:"Robertson County Scales", route:"I-65 NB",
location:{ city:"Cross Plains", state:"TN", lat:36.53, lng:-86.69 },
hours:"6am-10pm", prePass:true,
currentStatus:"open", lastFlagged:"2026-03-29T08:00:00Z", flaggedBy:"VolunteerEscort",
notes:"North of Nashville. Moderate traffic. Oversize loads may be pulled in for permit check." },
{ id:"WS-007", name:"Lodi Weigh Station", route:"I-71 SB",
location:{ city:"Lodi", state:"OH", lat:41.04, lng:-82.01 },
hours:"7am-7pm", prePass:true,
currentStatus:"closed", lastFlagged:"2026-03-28T17:00:00Z", flaggedBy:"BuckeyePilot",
notes:"Between Cleveland and Columbus on I-71. Intermittent operation — often closed on weekends." },
{ id:"WS-008", name:"Clearfield Weigh Station", route:"I-80 WB",
location:{ city:"Clearfield", state:"PA", lat:41.01, lng:-78.44 },
hours:"6am-10pm", prePass:false,
currentStatus:"open", lastFlagged:"2026-03-29T12:00:00Z", flaggedBy:"PA_HeavyHaul",
notes:"Central PA on I-80. Oversize loads inspected — have PA permit documentation ready." },
{ id:"WS-009", name:"Woodburn Port of Entry", route:"I-5 NB",
location:{ city:"Woodburn", state:"OR", lat:45.15, lng:-122.85 },
hours:"24/7", prePass:true,
currentStatus:"open", lastFlagged:"2026-03-29T07:30:00Z", flaggedBy:"PNW_Pilot",
notes:"Major I-5 checkpoint. All commercial vehicles must stop. Oregon has strict oversize enforcement." },
{ id:"WS-010", name:"Fargo Weigh Station", route:"I-94 WB",
location:{ city:"West Fargo", state:"ND", lat:46.87, lng:-96.92 },
hours:"7am-9pm", prePass:true,
currentStatus:"open", lastFlagged:"2026-03-29T13:00:00Z", flaggedBy:"PrairieHauler",
notes:"Minnesota/North Dakota border area. Oil field and wind energy traffic frequent. Oversize permits checked." },
{ id:"WS-011", name:"Marshall Weigh Station", route:"I-20 EB",
location:{ city:"Marshall", state:"TX", lat:32.54, lng:-94.37 },
hours:"24/7", prePass:true,
currentStatus:"open", lastFlagged:"2026-03-29T15:00:00Z", flaggedBy:"LoneStarEscort",
notes:"East Texas near Louisiana border. All commercial vehicles must stop when open." },
{ id:"WS-012", name:"Valdosta Weigh Station", route:"I-75 NB",
location:{ city:"Valdosta", state:"GA", lat:30.87, lng:-83.28 },
hours:"6am-10pm", prePass:true,
currentStatus:"closed", lastFlagged:"2026-03-28T20:00:00Z", flaggedBy:"SE_Oversized",
notes:"Florida/Georgia border on I-75. Oversize loads always pulled in when station is open." }
];
// =====================================================================
// ROUTE CONDITIONS (Module 7)
// =====================================================================
const MOCK_ROUTE_CONDITIONS = [
{ id:"RC-001", type:"construction", severity:"major",
route:"I-10 WB", location:{ desc:"Between Tucson and Phoenix", state:"AZ", lat:32.43, lng:-111.57 },
description:"Lane closure restricting width to 11'6\". Oversize loads over 12' wide CANNOT pass — contact ADOT for route amendment.",
startDate:"2026-03-01", endDate:"2026-06-30", source:"ADOT 511", affectsOversize:true },
{ id:"RC-002", type:"closure", severity:"critical",
route:"I-40 EB", location:{ desc:"Bridge replacement near Flagstaff", state:"AZ", lat:35.17, lng:-111.68 },
description:"Full eastbound closure 9pm-5am nightly. Oversize loads on single-trip permits must contact ADOT for revised routing or schedule around closure.",
startDate:"2026-03-15", endDate:"2026-05-15", source:"ADOT 511", affectsOversize:true },
{ id:"RC-003", type:"construction", severity:"moderate",
route:"I-35 NB/SB", location:{ desc:"Oklahoma City metro area", state:"OK", lat:35.47, lng:-97.52 },
description:"Ongoing I-35/I-44 interchange reconstruction. Lane shifts and temporary barriers — oversize loads limited to 14' wide through work zone.",
startDate:"2026-01-15", endDate:"2026-09-30", source:"ODOT", affectsOversize:true },
{ id:"RC-004", type:"construction", severity:"minor",
route:"I-80 EB", location:{ desc:"Near North Platte", state:"NE", lat:41.12, lng:-100.78 },
description:"Shoulder work — right lane may be narrowed. Oversize loads over 14' wide should use caution. No permits affected.",
startDate:"2026-04-01", endDate:"2026-04-15", source:"NDOT", affectsOversize:false },
{ id:"RC-005", type:"closure", severity:"major",
route:"US-93 NB", location:{ desc:"Mountain pass south of Missoula", state:"MT", lat:46.32, lng:-113.86 },
description:"Seasonal closure for snow removal. Route impassable for all traffic. Oversize loads must use I-90 alternate.",
startDate:"2025-11-15", endDate:"2026-04-30", source:"MDT", affectsOversize:true },
{ id:"RC-006", type:"construction", severity:"moderate",
route:"I-75 SB", location:{ desc:"Atlanta metro — I-285 interchange", state:"GA", lat:33.85, lng:-84.36 },
description:"Interchange reconstruction. Lane restrictions and temporary barriers. Oversize loads over 12' wide must travel between 9pm-5am through work zone.",
startDate:"2026-02-01", endDate:"2026-08-30", source:"GDOT", affectsOversize:true }
];
// =====================================================================
// WEATHER / WIND ALERTS (Module 8)
// =====================================================================
const MOCK_WEATHER_ALERTS = [
{ id:"WX-001", type:"wind", severity:"warning",
region:"Texas Panhandle / Western Oklahoma",
routes:["I-40", "US-287", "US-83"],
description:"High Wind Warning — sustained winds 40-50 mph with gusts to 65 mph. Wide loads (12'+) should NOT travel.",
validFrom:"2026-03-30T06:00:00Z", validTo:"2026-03-30T22:00:00Z",
source:"NWS Amarillo", lat:35.22, lng:-101.83 },
{ id:"WX-002", type:"wind", severity:"advisory",
region:"Wyoming I-80 corridor",
routes:["I-80", "US-30"],
description:"Wind Advisory — crosswinds 25-35 mph with gusts to 50 mph. Light/high-profile oversize loads use extreme caution.",
validFrom:"2026-03-30T12:00:00Z", validTo:"2026-03-31T06:00:00Z",
source:"NWS Riverton", lat:41.54, lng:-107.22 },
{ id:"WX-003", type:"winter", severity:"warning",
region:"Colorado Rocky Mountains",
routes:["I-70 west of Denver", "US-6 Loveland Pass"],
description:"Winter Storm Warning — 12-18\" snow expected above 9,000'. Chain law in effect on I-70 in mountains. Oversize travel not recommended.",
validFrom:"2026-03-30T00:00:00Z", validTo:"2026-03-31T12:00:00Z",
source:"NWS Denver", lat:39.68, lng:-105.91 },
{ id:"WX-004", type:"fog", severity:"advisory",
region:"Central California Valley",
routes:["I-5", "CA-99"],
description:"Dense Fog Advisory — visibility below 1/4 mile. Oversize loads should delay departure until fog lifts. Expected to clear by 10am.",
validFrom:"2026-03-30T04:00:00Z", validTo:"2026-03-30T17:00:00Z",
source:"NWS Hanford", lat:36.60, lng:-119.77 },
{ id:"WX-005", type:"thunderstorm", severity:"watch",
region:"Central Texas / Oklahoma",
routes:["I-35", "I-44", "US-69"],
description:"Severe Thunderstorm Watch — potential for large hail and damaging winds. Wide loads should seek shelter if storms develop.",
validFrom:"2026-03-30T18:00:00Z", validTo:"2026-03-31T02:00:00Z",
source:"NWS Norman", lat:34.20, lng:-97.40 }
];
// =====================================================================
// SEASONAL RESTRICTIONS (Module 15)
// =====================================================================
const MOCK_SEASONAL_RESTRICTIONS = [
{ id:"SR-001", state:"MN", stateName:"Minnesota", type:"spring_weight", color:"#3b82f6",
title:"Spring Weight Restrictions",
startMonth:3, startDay:1, endMonth:5, endDay:15,
routes:"Most state highways (interstates generally exempt)",
description:"Weight restrictions to prevent road damage during spring thaw. Exact dates vary annually based on frost conditions. Check MnDOT for current year dates.",
impact:"Reduced weight limits — overweight loads may need to delay or use interstate-only routing." },
{ id:"SR-002", state:"WI", stateName:"Wisconsin", type:"spring_weight", color:"#3b82f6",
title:"Spring Weight Restrictions (Frost Law)",
startMonth:3, startDay:1, endMonth:5, endDay:15,
routes:"State and county highways (interstates exempt)",
description:"Annual frost law restrictions. Posted roads have reduced weight limits during spring thaw period.",
impact:"Overweight loads restricted on posted routes. Plan for interstate-only routing." },
{ id:"SR-003", state:"ND", stateName:"North Dakota", type:"spring_weight", color:"#3b82f6",
title:"Spring Load Restrictions",
startMonth:3, startDay:1, endMonth:5, endDay:31,
routes:"State highways and county roads",
description:"Annual spring load restrictions. Oil field and wind energy loads frequently affected.",
impact:"Weight limits reduced on state highways. Heavy loads should delay or use approved routes." },
{ id:"SR-004", state:"CO", stateName:"Colorado", type:"winter_closure", color:"#6366f1",
title:"Mountain Pass Seasonal Closures",
startMonth:10, startDay:15, endMonth:5, endDay:30,
routes:"Independence Pass (CO-82), Cottonwood Pass, Hagerman Pass, various unpaved passes",
description:"High mountain passes close for winter. I-70 remains open but may have chain laws and traction requirements.",
impact:"Oversize loads must use lower-elevation routes. I-70 Eisenhower Tunnel has height/width restrictions." },
{ id:"SR-005", state:"MT", stateName:"Montana", type:"winter_closure", color:"#6366f1",
title:"Mountain Pass Restrictions",
startMonth:11, startDay:1, endMonth:4, endDay:30,
routes:"Beartooth Highway (US-212), Going-to-the-Sun Road, various forest roads",
description:"High passes close for winter. Major corridors (I-90, I-15) remain open but conditions vary.",
impact:"Alternative routing may be required. Check MDT road conditions before departure." },
{ id:"SR-006", state:"WY", stateName:"Wyoming", type:"wind_season", color:"#f59e0b",
title:"High Wind Season",
startMonth:11, startDay:1, endMonth:4, endDay:30,
routes:"I-80, I-25 (especially southern Wyoming)",
description:"Severe crosswinds are common October through April, especially on I-80. Wind closures can last hours or days.",
impact:"Wide loads (12'+) frequently delayed or stopped. Monitor WYDOT road conditions. Budget extra travel days." },
{ id:"SR-007", state:"TX", stateName:"Texas", type:"holiday_blackout", color:"#ef4444",
title:"Holiday Travel Blackouts",
startMonth:1, startDay:1, endMonth:12, endDay:31,
routes:"All routes statewide",
description:"No oversize load movement on: New Year's Day, Memorial Day weekend (Sat-Mon), July 4th, Labor Day weekend (Sat-Mon), Thanksgiving (Thu-Sun), Christmas (Dec 24-26).",
impact:"Schedule loads to avoid holiday blackout periods. Loads in transit must park and wait." },
{ id:"SR-008", state:"IA", stateName:"Iowa", type:"spring_weight", color:"#3b82f6",
title:"Spring Frost Restrictions",
startMonth:2, startDay:15, endMonth:5, endDay:15,
routes:"County roads and some state highways",
description:"Frost-related weight restrictions. Wind energy loads frequently affected as many wind farm access roads are county-maintained.",
impact:"Heavy loads may need to delay. County permits may be suspended during restriction period." },
{ id:"SR-009", state:"NY", stateName:"New York", type:"holiday_blackout", color:"#ef4444",
title:"NYC Metro Oversize Blackouts",
startMonth:1, startDay:1, endMonth:12, endDay:31,
routes:"All routes in NYC boroughs, George Washington Bridge, major bridges/tunnels",
description:"NYC restricts oversize movement year-round except with special NYPD escort. Additional blackouts during holidays, events, and UN General Assembly (September).",
impact:"Route around NYC whenever possible. Allow 2+ weeks for NYPD escort coordination." },
{ id:"SR-010", state:"OR", stateName:"Oregon", type:"harvest_season", color:"#22c55e",
title:"Harvest Season Restrictions",
startMonth:8, startDay:1, endMonth:10, endDay:31,
routes:"Agricultural areas — Willamette Valley, Eastern Oregon farming regions",
description:"Increased farm equipment on roads during harvest. Some county roads may have temporary restrictions or slow farm equipment traffic.",
impact:"Expect slower travel through agricultural areas. Farm equipment may block narrow roads." }
];
// =====================================================================
// MOCK DOCUMENTS (Module 9 — Document Vault demo)
// =====================================================================
const MOCK_DOCUMENTS = [
{ id:"DOC-001", name:"TX Single Trip Permit — Load #LB-2026-006", type:"permit", state:"TX",
uploadDate:"2026-03-28", expiryDate:"2026-04-15", fileSize:"245 KB", status:"active" },
{ id:"DOC-002", name:"OK Single Trip Permit — Load #LB-2026-006", type:"permit", state:"OK",
uploadDate:"2026-03-28", expiryDate:"2026-04-15", fileSize:"198 KB", status:"active" },
{ id:"DOC-003", name:"Commercial Auto Insurance — Policy #CAI-2026-445", type:"insurance",
uploadDate:"2026-01-15", expiryDate:"2026-07-15", fileSize:"1.2 MB", status:"active" },
{ id:"DOC-004", name:"General Liability Certificate", type:"insurance",
uploadDate:"2026-01-15", expiryDate:"2027-01-15", fileSize:"890 KB", status:"active" },
{ id:"DOC-005", name:"TX Pilot Car Certification", type:"certification", state:"TX",
uploadDate:"2025-09-10", expiryDate:"2027-09-10", fileSize:"156 KB", status:"active" },
{ id:"DOC-006", name:"CA PCET Certification", type:"certification", state:"CA",
uploadDate:"2025-06-20", expiryDate:"2027-06-20", fileSize:"178 KB", status:"active" },
{ id:"DOC-007", name:"OH Annual Oversize Permit — 2025", type:"permit", state:"OH",
uploadDate:"2025-03-01", expiryDate:"2026-02-28", fileSize:"312 KB", status:"expired" },
{ id:"DOC-008", name:"Vehicle Registration — 2024 Ford F-150", type:"registration",
uploadDate:"2026-02-01", expiryDate:"2027-02-01", fileSize:"98 KB", status:"active" }
];

630
public/js/mock-data.js Normal file
View File

@@ -0,0 +1,630 @@
// =====================================================================
// MOCK DATA — All data is SIMULATED for POC/demonstration purposes.
// Regulation data MUST be verified with official state DOT sources
// before any real-world use. Do NOT rely on these values for routing,
// permitting, or escort decisions.
// =====================================================================
const MOCK_STATE_REGULATIONS = [
{ name:"Alabama", abbr:"AL", lat:32.32, lng:-86.90,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"15'6\" (1 escort)", escortLength:"100' (1); 120'+ (2)", escortWeight:"150,000+ lbs",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement New Year's, Memorial Day, July 4th, Labor Day, Thanksgiving, Christmas",
agency:"ALDOT Maintenance Bureau", url:"https://www.dot.state.al.us/", notes:"Superloads require 10 business days advance notice. Annual permits available for routine oversize." },
{ name:"Alaska", abbr:"AK", lat:63.59, lng:-154.49,
permitWidth:"10'0\"", permitHeight:"15'0\"", permitLength:"75'", permitWeight:"80,000 lbs (varies by route)",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"17'0\" (height pole)", escortLength:"110' (1); 130'+ (2)", escortWeight:"200,000+ lbs",
travel:"Daylight hours only", holidays:"No movement on major state holidays",
agency:"Alaska DOT&PF", url:"https://dot.alaska.gov/", notes:"Extreme weather may restrict movement. Many routes are single-lane — plan accordingly." },
{ name:"Arizona", abbr:"AZ", lat:34.05, lng:-111.09,
permitWidth:"8'6\"", permitHeight:"14'0\"", permitLength:"65'", permitWeight:"80,000 lbs",
escortWidth:"12' (1 front); 16'+ (front & rear)", escortHeight:"16'0\" (1 escort)", escortLength:"100' (1); 120'+ (2)", escortWeight:"160,000+ lbs",
travel:"Sunrise to sunset", holidays:"No movement on major holidays",
agency:"ADOT Permits Office", url:"https://azdot.gov/", notes:"I-10, I-17, I-40 have specific oversize restrictions during peak hours." },
{ name:"Arkansas", abbr:"AR", lat:34.80, lng:-92.20,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"15'0\" (1 escort)", escortLength:"100' (1); 115'+ (2)", escortWeight:"150,000+ lbs",
travel:"30 min before sunrise to 30 min after sunset", holidays:"No movement on major holidays",
agency:"ArDOT Permits", url:"https://www.ardot.gov/", notes:"Many two-lane roads with limited shoulders — plan escorts carefully." },
{ name:"California", abbr:"CA", lat:36.78, lng:-119.42,
permitWidth:"8'6\"", permitHeight:"14'0\"", permitLength:"65'", permitWeight:"80,000 lbs",
escortWidth:"12' (1 front); 14'+ (front & rear)", escortHeight:"15'0\" (1 escort); 17'+ (height pole)", escortLength:"100' (1); 120'+ (2)", escortWeight:"150,000+ lbs",
travel:"Sunrise to sunset; some routes restricted to off-peak", holidays:"No movement on major holidays; Caltrans may restrict specific dates",
agency:"Caltrans Transportation Permits", url:"https://dot.ca.gov/programs/traffic-operations/transportation-permits", notes:"Strict environmental and bridge restrictions. Some routes require Caltrans survey. Pilot cars must meet CA certification requirements." },
{ name:"Colorado", abbr:"CO", lat:39.11, lng:-105.36,
permitWidth:"8'6\"", permitHeight:"14'6\"", permitLength:"70'", permitWeight:"80,000 lbs",
escortWidth:"13' (1 front); 16'+ (front & rear)", escortHeight:"16'0\" (1 escort)", escortLength:"100' (1); 120'+ (2)", escortWeight:"160,000+ lbs",
travel:"Sunrise to sunset", holidays:"No movement on major holidays",
agency:"CDOT Permits Unit", url:"https://www.codot.gov/", notes:"Mountain passes may have seasonal restrictions. I-70 tunnel restrictions for overheight." },
{ name:"Connecticut", abbr:"CT", lat:41.60, lng:-72.76,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"12' (1 front); 14'+ (front & rear)", escortHeight:"14'6\" (1 escort)", escortLength:"90' (1); 110'+ (2)", escortWeight:"120,000+ lbs",
travel:"Sunrise to sunset; some routes night-only", holidays:"No movement on major holidays or weekends",
agency:"CT DOT Office of Permits", url:"https://portal.ct.gov/dot", notes:"Dense state with many low overpasses. Weekend travel restrictions on many routes." },
{ name:"Delaware", abbr:"DE", lat:39.00, lng:-75.50,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"12' (1 front); 15'+ (front & rear)", escortHeight:"14'6\" (1 escort)", escortLength:"95' (1); 115'+ (2)", escortWeight:"130,000+ lbs",
travel:"Sunrise to sunset", holidays:"No movement on major holidays",
agency:"DelDOT Permits", url:"https://deldot.gov/", notes:"Small state but major freight corridor along I-95 and US-13." },
{ name:"Florida", abbr:"FL", lat:27.66, lng:-81.52,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"15'0\" (1 escort)", escortLength:"100' (1); 120'+ (2)", escortWeight:"160,000+ lbs",
travel:"30 min before sunrise to 30 min after sunset", holidays:"No movement on major holidays",
agency:"FDOT Permits Office", url:"https://www.fdot.gov/", notes:"Bridge restrictions on many coastal routes. Hurricane season may affect permit availability." },
{ name:"Georgia", abbr:"GA", lat:32.16, lng:-82.90,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"15'6\" (1 escort)", escortLength:"100' (1); 120'+ (2)", escortWeight:"150,000+ lbs",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement on major holidays",
agency:"GDOT Permits Office", url:"https://www.dot.ga.gov/", notes:"I-285 (Atlanta perimeter) has specific oversize restrictions during rush hours." },
{ name:"Hawaii", abbr:"HI", lat:19.90, lng:-155.58,
permitWidth:"9'0\"", permitHeight:"14'0\"", permitLength:"65'", permitWeight:"80,000 lbs (varies by island)",
escortWidth:"12' (1 front); 14'+ (front & rear)", escortHeight:"14'6\" (1 escort)", escortLength:"80' (1); 100'+ (2)", escortWeight:"100,000+ lbs",
travel:"Varies by island and route", holidays:"No movement on major holidays",
agency:"Hawaii DOT Highways", url:"https://hidot.hawaii.gov/", notes:"Island-specific regulations. Inter-island transport requires barge. Very limited oversize routing on most islands." },
{ name:"Idaho", abbr:"ID", lat:44.07, lng:-114.74,
permitWidth:"8'6\"", permitHeight:"14'0\"", permitLength:"75'", permitWeight:"105,500 lbs",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"16'0\" (1 escort)", escortLength:"105' (1); 125'+ (2)", escortWeight:"180,000+ lbs",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement on major holidays",
agency:"ITD Permits", url:"https://itd.idaho.gov/", notes:"Higher weight limits than most states. Mountain passes may have seasonal closures." },
{ name:"Illinois", abbr:"IL", lat:40.63, lng:-89.40,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"15'0\" (1 escort)", escortLength:"100' (1); 115'+ (2)", escortWeight:"150,000+ lbs",
travel:"Sunrise to sunset", holidays:"No movement on major holidays",
agency:"IDOT Permits", url:"https://idot.illinois.gov/", notes:"Chicago metro area has extensive oversize restrictions. I-294 and I-90/94 may require off-peak travel." },
{ name:"Indiana", abbr:"IN", lat:40.27, lng:-86.13,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"15'6\" (1 escort)", escortLength:"100' (1); 120'+ (2)", escortWeight:"150,000+ lbs",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement on major holidays",
agency:"INDOT Permits", url:"https://www.in.gov/indot/", notes:"Major crossroads state — high oversize traffic on I-65, I-70, I-69." },
{ name:"Iowa", abbr:"IA", lat:41.88, lng:-93.10,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"14'6\" (1 front); 16'+ (front & rear)", escortHeight:"15'6\" (1 escort)", escortLength:"100' (1); 120'+ (2)", escortWeight:"156,000+ lbs",
travel:"Sunrise to sunset", holidays:"No movement on major holidays",
agency:"Iowa DOT Motor Vehicle", url:"https://iowadot.gov/", notes:"Wind turbine corridor — frequent oversize loads on I-35 and I-80. Annual permits available." },
{ name:"Kansas", abbr:"KS", lat:39.01, lng:-98.48,
permitWidth:"8'6\"", permitHeight:"14'0\"", permitLength:"65'", permitWeight:"85,500 lbs",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"16'0\" (1 escort)", escortLength:"110' (1); 130'+ (2)", escortWeight:"160,000+ lbs",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement on major holidays",
agency:"KDOT Division of Operations", url:"https://www.ksdot.gov/", notes:"Wide open terrain but high wind exposure. I-70 is primary east-west oversize corridor." },
{ name:"Kentucky", abbr:"KY", lat:37.84, lng:-84.27,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"14' (1 front); 15'+ (front & rear)", escortHeight:"15'0\" (1 escort)", escortLength:"100' (1); 115'+ (2)", escortWeight:"150,000+ lbs",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement on major holidays",
agency:"KYTC Department of Vehicle Regulation", url:"https://transportation.ky.gov/", notes:"Mountainous terrain in eastern KY limits some oversize routing." },
{ name:"Louisiana", abbr:"LA", lat:30.98, lng:-91.96,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"15'0\" (1 escort)", escortLength:"100' (1); 120'+ (2)", escortWeight:"160,000+ lbs",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement on major holidays; Mardi Gras restrictions in some areas",
agency:"DOTD Permits", url:"https://www.dotd.la.gov/", notes:"Many bridges with weight restrictions. Petrochemical industry generates frequent heavy/oversize loads." },
{ name:"Maine", abbr:"ME", lat:45.37, lng:-69.45,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"13' (1 front); 15'+ (front & rear)", escortHeight:"14'6\" (1 escort)", escortLength:"95' (1); 110'+ (2)", escortWeight:"130,000+ lbs",
travel:"Sunrise to sunset", holidays:"No movement on major holidays",
agency:"MaineDOT", url:"https://www.maine.gov/mdot/", notes:"Wind energy projects in northern Maine. Limited highway infrastructure in rural areas." },
{ name:"Maryland", abbr:"MD", lat:39.05, lng:-76.64,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"55'", permitWeight:"80,000 lbs",
escortWidth:"12' (1 front); 14'+ (front & rear)", escortHeight:"14'6\" (1 escort)", escortLength:"90' (1); 110'+ (2)", escortWeight:"120,000+ lbs",
travel:"Sunrise to sunset; night moves possible with special authorization", holidays:"No movement on major holidays or weekends without special permit",
agency:"MDOT SHA Hauling Permits", url:"https://www.roads.maryland.gov/", notes:"Baltimore/DC metro restrictions. Chesapeake Bay Bridge has strict oversize limitations." },
{ name:"Massachusetts", abbr:"MA", lat:42.41, lng:-71.38,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"55'", permitWeight:"80,000 lbs",
escortWidth:"12' (1 front); 14'+ (front & rear)", escortHeight:"14'0\" (1 escort)", escortLength:"85' (1); 105'+ (2)", escortWeight:"120,000+ lbs",
travel:"Varies by route — many night-only requirements", holidays:"No movement on weekends or holidays without special permit",
agency:"MassDOT Permits", url:"https://www.mass.gov/massdot", notes:"Very restricted for oversize. Many moves must be done at night. Low overpasses throughout." },
{ name:"Michigan", abbr:"MI", lat:44.31, lng:-85.60,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"14'6\" (1 front); 16'+ (front & rear)", escortHeight:"15'0\" (1 escort)", escortLength:"100' (1); 120'+ (2)", escortWeight:"160,000+ lbs",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement on major holidays",
agency:"MDOT Permits Unit", url:"https://www.michigan.gov/mdot", notes:"Mackinac Bridge has strict oversize limitations and may require escort by bridge authority." },
{ name:"Minnesota", abbr:"MN", lat:46.73, lng:-94.69,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"75'", permitWeight:"80,000 lbs",
escortWidth:"14'6\" (1 front); 16'+ (front & rear)", escortHeight:"15'6\" (1 escort)", escortLength:"100' (1); 120'+ (2)", escortWeight:"160,000+ lbs",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement on major holidays",
agency:"MnDOT Office of Freight & Commercial Vehicle Operations", url:"https://www.dot.state.mn.us/", notes:"Spring weight restrictions on many roads. Wind energy transport corridor." },
{ name:"Mississippi", abbr:"MS", lat:32.35, lng:-89.40,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"15'0\" (1 escort)", escortLength:"100' (1); 115'+ (2)", escortWeight:"150,000+ lbs",
travel:"Sunrise to sunset", holidays:"No movement on major holidays",
agency:"MDOT Permits Division", url:"https://mdot.ms.gov/", notes:"Bridge weight restrictions on many state routes." },
{ name:"Missouri", abbr:"MO", lat:37.96, lng:-91.83,
permitWidth:"8'6\"", permitHeight:"14'0\"", permitLength:"65'", permitWeight:"80,000 lbs",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"15'6\" (1 escort)", escortLength:"100' (1); 120'+ (2)", escortWeight:"160,000+ lbs",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement on major holidays",
agency:"MoDOT Motor Carrier Services", url:"https://www.modot.org/", notes:"Major I-70 and I-44 freight corridor. Kansas City and St. Louis metro restrictions." },
{ name:"Montana", abbr:"MT", lat:46.88, lng:-110.36,
permitWidth:"8'6\"", permitHeight:"14'0\"", permitLength:"75'", permitWeight:"80,000 lbs",
escortWidth:"14'6\" (1 front); 16'+ (front & rear)", escortHeight:"16'0\" (1 escort)", escortLength:"110' (1); 130'+ (2)", escortWeight:"180,000+ lbs",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement on major holidays",
agency:"MDT Motor Carrier Services", url:"https://www.mdt.mt.gov/", notes:"Long distances between services. Mountain passes may close seasonally. Mining equipment transport common." },
{ name:"Nebraska", abbr:"NE", lat:41.49, lng:-99.90,
permitWidth:"8'6\"", permitHeight:"14'6\"", permitLength:"75'", permitWeight:"80,000 lbs",
escortWidth:"14'6\" (1 front); 16'+ (front & rear)", escortHeight:"16'0\" (1 escort)", escortLength:"110' (1); 125'+ (2)", escortWeight:"160,000+ lbs",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement on major holidays",
agency:"NDOT Permits Division", url:"https://dot.nebraska.gov/", notes:"Major wind energy corridor. I-80 primary oversize route." },
{ name:"Nevada", abbr:"NV", lat:38.80, lng:-116.42,
permitWidth:"8'6\"", permitHeight:"14'0\"", permitLength:"70'", permitWeight:"80,000 lbs",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"16'0\" (1 escort)", escortLength:"105' (1); 125'+ (2)", escortWeight:"170,000+ lbs",
travel:"Sunrise to sunset", holidays:"No movement on major holidays",
agency:"NDOT Permits", url:"https://www.dot.nv.gov/", notes:"Desert conditions — carry extra water and supplies. Solar/mining equipment transport frequent." },
{ name:"New Hampshire", abbr:"NH", lat:43.19, lng:-71.57,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"12' (1 front); 14'+ (front & rear)", escortHeight:"14'6\" (1 escort)", escortLength:"90' (1); 110'+ (2)", escortWeight:"120,000+ lbs",
travel:"Sunrise to sunset", holidays:"No movement on major holidays",
agency:"NHDOT Bureau of Highway Maintenance", url:"https://www.nh.gov/dot/", notes:"Mountain terrain with tight curves. Many covered bridges with strict height/weight limits." },
{ name:"New Jersey", abbr:"NJ", lat:40.06, lng:-74.41,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"55'", permitWeight:"80,000 lbs",
escortWidth:"12' (1 front); 14'+ (front & rear)", escortHeight:"14'0\" (1 escort)", escortLength:"85' (1); 105'+ (2)", escortWeight:"120,000+ lbs",
travel:"Night moves often required in metro areas", holidays:"No movement on weekends or holidays",
agency:"NJDOT Permits Bureau", url:"https://www.nj.gov/transportation/", notes:"Very dense state — many moves require night travel. NJ Turnpike and Garden State Parkway have strict restrictions." },
{ name:"New Mexico", abbr:"NM", lat:34.52, lng:-105.87,
permitWidth:"8'6\"", permitHeight:"14'0\"", permitLength:"65'", permitWeight:"80,000 lbs",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"16'0\" (1 escort)", escortLength:"110' (1); 125'+ (2)", escortWeight:"170,000+ lbs",
travel:"Sunrise to sunset", holidays:"No movement on major holidays",
agency:"NMDOT Motor Transportation Division", url:"https://www.dot.nm.gov/", notes:"Long distances between services. High winds in eastern plains. I-25 and I-40 main corridors." },
{ name:"New York", abbr:"NY", lat:43.00, lng:-75.00,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"55'", permitWeight:"80,000 lbs",
escortWidth:"12' (1 front); 14'+ (front & rear)", escortHeight:"14'0\" (1 escort)", escortLength:"85' (1); 100'+ (2)", escortWeight:"120,000+ lbs",
travel:"Varies — night moves required in NYC metro", holidays:"No movement on holidays or weekends in metro areas",
agency:"NYSDOT Special Hauling Permits", url:"https://www.dot.ny.gov/", notes:"NYC boroughs have extreme restrictions — most oversize prohibited. Upstate much more permissive. Thruway has separate permit process." },
{ name:"North Carolina", abbr:"NC", lat:35.76, lng:-79.02,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"15'0\" (1 escort)", escortLength:"100' (1); 115'+ (2)", escortWeight:"150,000+ lbs",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement on major holidays",
agency:"NCDOT Oversize/Overweight Permits", url:"https://www.ncdot.gov/", notes:"Mountain routes in western NC have significant restrictions. I-85 and I-40 primary corridors." },
{ name:"North Dakota", abbr:"ND", lat:47.55, lng:-101.00,
permitWidth:"8'6\"", permitHeight:"14'0\"", permitLength:"75'", permitWeight:"105,500 lbs",
escortWidth:"14'6\" (1 front); 16'+ (front & rear)", escortHeight:"16'0\" (1 escort)", escortLength:"110' (1); 130'+ (2)", escortWeight:"200,000+ lbs",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement on major holidays",
agency:"NDDOT Motor Carrier", url:"https://www.dot.nd.gov/", notes:"Oil field equipment transport very common. Higher weight limits than most states. Spring weight restrictions." },
{ name:"Ohio", abbr:"OH", lat:40.42, lng:-82.91,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"15'0\" (1 escort)", escortLength:"100' (1); 115'+ (2)", escortWeight:"150,000+ lbs",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement on major holidays",
agency:"ODOT Office of Permits", url:"https://www.transportation.ohio.gov/", notes:"Major manufacturing state — frequent transformer and heavy equipment loads. I-75, I-71, I-77 main corridors." },
{ name:"Oklahoma", abbr:"OK", lat:35.47, lng:-97.52,
permitWidth:"8'6\"", permitHeight:"14'0\"", permitLength:"65'", permitWeight:"80,000 lbs",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"16'0\" (1 escort)", escortLength:"110' (1); 125'+ (2)", escortWeight:"160,000+ lbs",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement on major holidays",
agency:"ODOT Motor Carrier Permits", url:"https://oklahoma.gov/odot.html", notes:"Wind energy transport major industry. Turnpike system has separate oversize rules." },
{ name:"Oregon", abbr:"OR", lat:43.80, lng:-120.55,
permitWidth:"8'6\"", permitHeight:"14'0\"", permitLength:"65'", permitWeight:"80,000 lbs",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"15'6\" (1 escort)", escortLength:"105' (1); 120'+ (2)", escortWeight:"160,000+ lbs",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement on major holidays",
agency:"ODOT Motor Carrier Transportation Division", url:"https://www.oregon.gov/odot/", notes:"Cascade Range creates routing challenges. Wind farm transport increasing. Portland metro restrictions." },
{ name:"Pennsylvania", abbr:"PA", lat:41.20, lng:-77.19,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"13' (1 front); 15'+ (front & rear)", escortHeight:"14'6\" (1 escort)", escortLength:"95' (1); 110'+ (2)", escortWeight:"130,000+ lbs",
travel:"Sunrise to sunset; Turnpike 11pm-5am for superloads", holidays:"No movement on major holidays",
agency:"PennDOT Permits", url:"https://www.penndot.pa.gov/", notes:"Pennsylvania Turnpike has separate permit process. Many old bridges with weight limits. Hilly terrain throughout." },
{ name:"Rhode Island", abbr:"RI", lat:41.58, lng:-71.48,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"55'", permitWeight:"80,000 lbs",
escortWidth:"12' (1 front); 14'+ (front & rear)", escortHeight:"14'0\" (1 escort)", escortLength:"85' (1); 100'+ (2)", escortWeight:"110,000+ lbs",
travel:"Varies — often night only", holidays:"No movement on weekends or holidays",
agency:"RIDOT Permits", url:"https://www.dot.ri.gov/", notes:"Smallest state but dense infrastructure. Most moves cross into MA or CT — coordinate multi-state." },
{ name:"South Carolina", abbr:"SC", lat:33.84, lng:-81.16,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"15'0\" (1 escort)", escortLength:"100' (1); 115'+ (2)", escortWeight:"150,000+ lbs",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement on major holidays",
agency:"SCDOT Oversize/Overweight Permits", url:"https://www.scdot.org/", notes:"Port of Charleston generates significant oversize freight. I-26 and I-95 main corridors." },
{ name:"South Dakota", abbr:"SD", lat:43.97, lng:-99.90,
permitWidth:"8'6\"", permitHeight:"14'0\"", permitLength:"75'", permitWeight:"80,000 lbs",
escortWidth:"14'6\" (1 front); 16'+ (front & rear)", escortHeight:"16'0\" (1 escort)", escortLength:"110' (1); 130'+ (2)", escortWeight:"180,000+ lbs",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement on major holidays",
agency:"SDDOT Motor Carrier", url:"https://dot.sd.gov/", notes:"Wind energy and oil field transport. Spring weight restrictions on many routes." },
{ name:"Tennessee", abbr:"TN", lat:35.52, lng:-86.58,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"15'0\" (1 escort)", escortLength:"100' (1); 115'+ (2)", escortWeight:"150,000+ lbs",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement on major holidays",
agency:"TDOT Permits Office", url:"https://www.tn.gov/tdot.html", notes:"Major north-south corridor for oversize. Nashville/Memphis metro restrictions during peak hours." },
{ name:"Texas", abbr:"TX", lat:31.97, lng:-99.90,
permitWidth:"8'6\"", permitHeight:"14'0\"", permitLength:"65'", permitWeight:"80,000 lbs",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"17'0\" (height pole vehicle)", escortLength:"110' (1); 125'+ (2)", escortWeight:"200,000+ lbs (route-specific)",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement on major state/federal holidays",
agency:"TxDMV Motor Carrier Division", url:"https://www.txdmv.gov/oversize-overweight-permits", notes:"Largest volume of oversize permits nationally. Annual permits available for routine oversize. Superloads over 254,300 lbs require TxDOT route study. Wind energy transport very common." },
{ name:"Utah", abbr:"UT", lat:39.32, lng:-111.09,
permitWidth:"8'6\"", permitHeight:"14'0\"", permitLength:"65'", permitWeight:"80,000 lbs",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"16'0\" (1 escort)", escortLength:"105' (1); 120'+ (2)", escortWeight:"170,000+ lbs",
travel:"Sunrise to sunset", holidays:"No movement on major holidays",
agency:"UDOT Motor Carrier Permits", url:"https://www.udot.utah.gov/", notes:"Canyon roads and mountain passes create routing challenges. Mining and energy equipment transport common." },
{ name:"Vermont", abbr:"VT", lat:44.56, lng:-72.58,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"12' (1 front); 14'+ (front & rear)", escortHeight:"14'6\" (1 escort)", escortLength:"90' (1); 105'+ (2)", escortWeight:"120,000+ lbs",
travel:"Sunrise to sunset", holidays:"No movement on major holidays",
agency:"VTrans Permits", url:"https://vtrans.vermont.gov/", notes:"Covered bridges limit many routes. Mountain roads with tight switchbacks. Wind energy transport increasing." },
{ name:"Virginia", abbr:"VA", lat:37.43, lng:-78.66,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"13' (1 front); 15'+ (front & rear)", escortHeight:"14'6\" (1 escort)", escortLength:"95' (1); 110'+ (2)", escortWeight:"140,000+ lbs",
travel:"Sunrise to sunset", holidays:"No movement on major holidays",
agency:"VDOT Permits", url:"https://www.virginiadot.org/", notes:"Northern VA/DC metro restrictions very strict. Hampton Roads port generates oversize traffic. Blue Ridge Parkway prohibited for oversize." },
{ name:"Washington", abbr:"WA", lat:47.75, lng:-120.74,
permitWidth:"8'6\"", permitHeight:"14'0\"", permitLength:"65'", permitWeight:"80,000 lbs",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"15'6\" (1 escort)", escortLength:"105' (1); 120'+ (2)", escortWeight:"160,000+ lbs",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement on major holidays",
agency:"WSDOT Motor Carrier", url:"https://wsdot.wa.gov/", notes:"Cascade passes may close in winter. Seattle/Tacoma metro restrictions. Port traffic generates oversize loads." },
{ name:"West Virginia", abbr:"WV", lat:38.60, lng:-80.45,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"13' (1 front); 15'+ (front & rear)", escortHeight:"15'0\" (1 escort)", escortLength:"95' (1); 110'+ (2)", escortWeight:"140,000+ lbs",
travel:"Sunrise to sunset", holidays:"No movement on major holidays",
agency:"WV DOH Permits", url:"https://transportation.wv.gov/", notes:"Very mountainous — many routes not suitable for oversize. Tunnels and narrow roads throughout. Coal/energy equipment transport." },
{ name:"Wisconsin", abbr:"WI", lat:43.78, lng:-88.79,
permitWidth:"8'6\"", permitHeight:"13'6\"", permitLength:"60'", permitWeight:"80,000 lbs",
escortWidth:"14' (1 front); 16'+ (front & rear)", escortHeight:"15'6\" (1 escort)", escortLength:"100' (1); 120'+ (2)", escortWeight:"150,000+ lbs",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement on major holidays",
agency:"WisDOT Oversize Permits", url:"https://wisconsindot.gov/", notes:"Spring weight restrictions March-May. Milwaukee metro restrictions. Manufacturing equipment transport common." },
{ name:"Wyoming", abbr:"WY", lat:43.08, lng:-107.29,
permitWidth:"8'6\"", permitHeight:"14'0\"", permitLength:"75'", permitWeight:"80,000 lbs",
escortWidth:"14'6\" (1 front); 16'+ (front & rear)", escortHeight:"16'0\" (1 escort)", escortLength:"110' (1); 130'+ (2)", escortWeight:"180,000+ lbs",
travel:"30 min after sunrise to 30 min before sunset", holidays:"No movement on major holidays",
agency:"WYDOT Permits", url:"https://www.dot.state.wy.us/", notes:"Extreme wind conditions common. I-80 frequently closed for wind. Wind energy and mining equipment transport." },
{ name:"District of Columbia", abbr:"DC", lat:38.91, lng:-77.04,
permitWidth:"8'0\"", permitHeight:"12'6\"", permitLength:"50'", permitWeight:"70,000 lbs",
escortWidth:"10' (1 front); 12'+ (front & rear, police escort may be required)", escortHeight:"13'6\" (requires police escort)", escortLength:"75' (police escort required)", escortWeight:"100,000+ lbs (special authorization only)",
travel:"Night only — typically 9pm to 6am", holidays:"No movement on holidays, weekends, or during special events",
agency:"DDOT Permits", url:"https://ddot.dc.gov/", notes:"Extremely restricted for oversize. Most loads must travel at night with police escort. Avoid if possible — route around DC." }
];
// =====================================================================
// MOCK LOAD BOARD DATA
// =====================================================================
const MOCK_LOAD_BOARD = [
{
id: "LB-2026-001",
carrier: "Midwest Heavy Haul LLC",
origin: { city: "Des Moines", state: "IA", lat: 41.59, lng: -93.62 },
destination: { city: "Amarillo", state: "TX", lat: 35.22, lng: -101.83 },
departureDate: "2026-04-05",
dimensions: { width: "16'2\"", height: "14'8\"", length: "135'", weight: "185,000 lbs" },
description: "Wind turbine blade — 3-blade shipment, this is blade 1 of 3",
escortsNeeded: 2,
status: "posted",
postedDate: "2026-03-28",
contact: "dispatch@midwestheavy.example.com"
},
{
id: "LB-2026-002",
carrier: "Southern Power Transport Inc",
origin: { city: "Chattanooga", state: "TN", lat: 35.05, lng: -85.31 },
destination: { city: "Savannah", state: "GA", lat: 32.08, lng: -81.10 },
departureDate: "2026-04-08",
dimensions: { width: "14'0\"", height: "15'6\"", length: "95'", weight: "245,000 lbs" },
description: "Industrial transformer for Georgia Power substation",
escortsNeeded: 2,
status: "posted",
postedDate: "2026-03-27",
contact: "loads@southernpower.example.com"
},
{
id: "LB-2026-003",
carrier: "Pacific Coast Logistics",
origin: { city: "Sacramento", state: "CA", lat: 38.58, lng: -121.49 },
destination: { city: "Reno", state: "NV", lat: 39.53, lng: -119.81 },
departureDate: "2026-04-03",
dimensions: { width: "18'0\"", height: "13'2\"", length: "72'", weight: "95,000 lbs" },
description: "Pre-fabricated modular building section for data center",
escortsNeeded: 2,
status: "posted",
postedDate: "2026-03-29",
contact: "dispatch@pacificcoast.example.com"
},
{
id: "LB-2026-004",
carrier: "Keystone Crane & Rigging",
origin: { city: "Harrisburg", state: "PA", lat: 40.27, lng: -76.88 },
destination: { city: "Newark", state: "NJ", lat: 40.74, lng: -74.17 },
departureDate: "2026-04-10",
dimensions: { width: "12'4\"", height: "14'0\"", length: "110'", weight: "145,000 lbs" },
description: "Liebherr LTM 1300 crane boom section",
escortsNeeded: 1,
status: "posted",
postedDate: "2026-03-30",
contact: "ops@keystonecrane.example.com"
},
{
id: "LB-2026-005",
carrier: "Hoosier Heavy Transport",
origin: { city: "Gary", state: "IN", lat: 41.59, lng: -87.35 },
destination: { city: "Memphis", state: "TN", lat: 35.15, lng: -90.05 },
departureDate: "2026-04-07",
dimensions: { width: "11'8\"", height: "13'0\"", length: "82'", weight: "120,000 lbs" },
description: "Steel bridge girder — first of 4-piece set",
escortsNeeded: 1,
status: "posted",
postedDate: "2026-03-26",
contact: "freight@hoosierheavy.example.com"
},
{
id: "LB-2026-006",
carrier: "Lone Star Oversize LLC",
origin: { city: "Houston", state: "TX", lat: 29.76, lng: -95.37 },
destination: { city: "Oklahoma City", state: "OK", lat: 35.47, lng: -97.52 },
departureDate: "2026-04-12",
dimensions: { width: "15'0\"", height: "16'2\"", length: "68'", weight: "198,000 lbs" },
description: "Caterpillar 6060 mining excavator",
escortsNeeded: 2,
status: "posted",
postedDate: "2026-03-29",
contact: "dispatch@lonestoros.example.com"
},
{
id: "LB-2026-007",
carrier: "Carolina Modular Transport",
origin: { city: "Charlotte", state: "NC", lat: 35.23, lng: -80.84 },
destination: { city: "Jacksonville", state: "FL", lat: 30.33, lng: -81.66 },
departureDate: "2026-04-14",
dimensions: { width: "16'0\"", height: "14'4\"", length: "76'", weight: "82,000 lbs" },
description: "Modular home — half-section, 2 loads total",
escortsNeeded: 1,
status: "posted",
postedDate: "2026-03-30",
contact: "loads@carolinamod.example.com"
},
{
id: "LB-2026-008",
carrier: "Gulf Pipeline Services",
origin: { city: "Baton Rouge", state: "LA", lat: 30.45, lng: -91.19 },
destination: { city: "Hattiesburg", state: "MS", lat: 31.33, lng: -89.29 },
departureDate: "2026-04-06",
dimensions: { width: "12'0\"", height: "12'6\"", length: "95'", weight: "110,000 lbs" },
description: "48-inch pipeline section, coated and ready for burial",
escortsNeeded: 1,
status: "in_transit",
postedDate: "2026-03-22",
contact: "ops@gulfpipeline.example.com"
},
{
id: "LB-2026-009",
carrier: "Badger State Heavy Haul",
origin: { city: "Milwaukee", state: "WI", lat: 43.04, lng: -87.91 },
destination: { city: "Peoria", state: "IL", lat: 40.69, lng: -89.59 },
departureDate: "2026-04-15",
dimensions: { width: "14'8\"", height: "15'0\"", length: "88'", weight: "165,000 lbs" },
description: "Caterpillar diesel generator for manufacturing plant",
escortsNeeded: 1,
status: "posted",
postedDate: "2026-03-28",
contact: "dispatch@badgerheavy.example.com"
},
{
id: "LB-2026-010",
carrier: "Rocky Mountain Logistics",
origin: { city: "Billings", state: "MT", lat: 45.78, lng: -108.50 },
destination: { city: "Spokane", state: "WA", lat: 47.66, lng: -117.43 },
departureDate: "2026-04-09",
dimensions: { width: "13'6\"", height: "15'8\"", length: "104'", weight: "210,000 lbs" },
description: "Pressure vessel for refinery — requires height pole",
escortsNeeded: 2,
status: "posted",
postedDate: "2026-03-27",
contact: "freight@rockymtnlog.example.com"
},
{
id: "LB-2026-011",
carrier: "Palmetto Oversize Inc",
origin: { city: "Columbia", state: "SC", lat: 34.00, lng: -81.03 },
destination: { city: "Montgomery", state: "AL", lat: 32.37, lng: -86.30 },
departureDate: "2026-04-11",
dimensions: { width: "11'4\"", height: "14'2\"", length: "78'", weight: "135,000 lbs" },
description: "Industrial boiler for power plant",
escortsNeeded: 1,
status: "posted",
postedDate: "2026-03-29",
contact: "dispatch@palmettoos.example.com"
},
{
id: "LB-2026-012",
carrier: "Desert Sun Transport",
origin: { city: "Phoenix", state: "AZ", lat: 33.45, lng: -112.07 },
destination: { city: "Denver", state: "CO", lat: 39.74, lng: -104.99 },
departureDate: "2026-04-16",
dimensions: { width: "14'6\"", height: "17'4\"", length: "92'", weight: "175,000 lbs" },
description: "Mining haul truck bed — Komatsu 930E component",
escortsNeeded: 2,
status: "posted",
postedDate: "2026-03-30",
contact: "loads@desertsuntx.example.com"
}
];
// =====================================================================
// MOCK ESCORT OPERATORS
// =====================================================================
const MOCK_ESCORT_OPERATORS = [
{
id: "EO-001", name: "Mike's Pilot Car Service",
location: { city: "Dallas", state: "TX", lat: 32.78, lng: -96.80 },
status: "available",
certifications: ["TX", "OK", "LA", "AR", "NM"],
vehicleType: "2024 Ford F-150 — Amber lights, height pole, full signage",
rating: 4.9, totalJobs: 342,
experience: "12 years",
contact: "mike@mikespilotcar.example.com",
phone: "(214) 555-0187",
bio: "Veteran pilot car operator specializing in wind energy and heavy haul escort across the southern plains."
},
{
id: "EO-002", name: "Pacific Escort Services",
location: { city: "Sacramento", state: "CA", lat: 38.58, lng: -121.49 },
status: "available",
certifications: ["CA", "NV", "OR", "AZ"],
vehicleType: "2023 Chevy Silverado — CA certified, height pole, oversize banners",
rating: 4.8, totalJobs: 218,
experience: "8 years",
contact: "dispatch@pacificescort.example.com",
phone: "(916) 555-0234",
bio: "California-certified pilot car service. Experienced in Caltrans routes and mountain pass escorts."
},
{
id: "EO-003", name: "Buckeye Pilot Vehicles",
location: { city: "Columbus", state: "OH", lat: 39.96, lng: -82.99 },
status: "available",
certifications: ["OH", "PA", "IN", "MI", "WV", "KY"],
vehicleType: "2025 RAM 1500 — Full lighting package, CB radio, GPS tracking",
rating: 4.7, totalJobs: 189,
experience: "6 years",
contact: "info@buckeyepilot.example.com",
phone: "(614) 555-0312",
bio: "Midwest corridor specialist. Regular runs through the Ohio Valley and Great Lakes region."
},
{
id: "EO-004", name: "Keystone Escort Co",
location: { city: "Harrisburg", state: "PA", lat: 40.27, lng: -76.88 },
status: "on_job",
certifications: ["PA", "NJ", "NY", "DE", "MD", "CT"],
vehicleType: "2024 Ford F-250 — Night lighting package, height pole, DOT signage",
rating: 4.9, totalJobs: 276,
experience: "10 years",
contact: "dispatch@keystoneescort.example.com",
phone: "(717) 555-0145",
bio: "Northeast corridor expert. Experienced with night moves in metro areas and PA Turnpike superloads."
},
{
id: "EO-005", name: "Peach State Pilots",
location: { city: "Atlanta", state: "GA", lat: 33.75, lng: -84.39 },
status: "available",
certifications: ["GA", "SC", "NC", "FL", "AL", "TN"],
vehicleType: "2023 Toyota Tundra — Full safety package, height pole, LED arrows",
rating: 4.6, totalJobs: 154,
experience: "5 years",
contact: "dispatch@peachstatepilots.example.com",
phone: "(404) 555-0278",
bio: "Southeast specialist covering the I-85 and I-75 corridors. Port of Savannah regular."
},
{
id: "EO-006", name: "Sunshine Escort Vehicles",
location: { city: "Orlando", state: "FL", lat: 28.54, lng: -81.38 },
status: "available",
certifications: ["FL", "GA", "AL", "SC"],
vehicleType: "2024 Chevy Colorado — Amber lights, OVERSIZE LOAD signs, CB radio",
rating: 4.5, totalJobs: 98,
experience: "3 years",
contact: "info@sunshineescort.example.com",
phone: "(407) 555-0391",
bio: "Florida specialist. Experienced with coastal routes and bridge clearances."
},
{
id: "EO-007", name: "Crossroads Pilot Service",
location: { city: "Indianapolis", state: "IN", lat: 39.77, lng: -86.16 },
status: "available",
certifications: ["IN", "OH", "IL", "MI", "KY"],
vehicleType: "2024 Ford Ranger — Height pole, full lighting, dual CB radios",
rating: 4.8, totalJobs: 231,
experience: "9 years",
contact: "dispatch@crossroadspilot.example.com",
phone: "(317) 555-0456",
bio: "Indianapolis-based, covering the crossroads of America. Specialize in I-65 and I-70 corridor escorts."
},
{
id: "EO-008", name: "Prairie Pilot Cars",
location: { city: "Springfield", state: "IL", lat: 39.78, lng: -89.65 },
status: "on_job",
certifications: ["IL", "MO", "IA", "WI", "IN"],
vehicleType: "2023 GMC Sierra — Full escort package, arrow board",
rating: 4.7, totalJobs: 167,
experience: "7 years",
contact: "ops@prairiepilot.example.com",
phone: "(217) 555-0523",
bio: "Central Illinois based. Wind turbine blade escort specialist on I-39 and I-55 corridors."
},
{
id: "EO-009", name: "Tar Heel Escorts LLC",
location: { city: "Charlotte", state: "NC", lat: 35.23, lng: -80.84 },
status: "available",
certifications: ["NC", "SC", "VA", "TN", "GA"],
vehicleType: "2025 Toyota Tacoma — Full pilot car setup, height pole, GPS",
rating: 4.6, totalJobs: 143,
experience: "4 years",
contact: "info@tarheelescorts.example.com",
phone: "(704) 555-0612",
bio: "Carolina specialist. Experienced with I-85 corridor and mountain routes in western NC."
},
{
id: "EO-010", name: "Bayou Escort Services",
location: { city: "Baton Rouge", state: "LA", lat: 30.45, lng: -91.19 },
status: "available",
certifications: ["LA", "TX", "MS", "AR"],
vehicleType: "2024 Ford F-150 — Full light bar, height pole, waterproof signage",
rating: 4.8, totalJobs: 205,
experience: "11 years",
contact: "dispatch@bayouescort.example.com",
phone: "(225) 555-0789",
bio: "Gulf Coast specialist. Regular petrochemical and refinery equipment escorts. Expert in LA bridge routes."
},
{
id: "EO-011", name: "Sooner Pilot Vehicle Co",
location: { city: "Oklahoma City", state: "OK", lat: 35.47, lng: -97.52 },
status: "available",
certifications: ["OK", "TX", "KS", "AR", "MO"],
vehicleType: "2024 RAM 1500 — Full escort setup, dual amber lights",
rating: 4.7, totalJobs: 178,
experience: "8 years",
contact: "info@soonerpilot.example.com",
phone: "(405) 555-0834",
bio: "Oklahoma wind energy corridor specialist. Regular blade and tower section escorts on I-35 and I-40."
},
{
id: "EO-012", name: "Volunteer State Escorts",
location: { city: "Nashville", state: "TN", lat: 36.16, lng: -86.78 },
status: "on_job",
certifications: ["TN", "KY", "AL", "GA", "MS", "AR"],
vehicleType: "2023 Chevy Silverado — Amber light bar, height pole, arrow board, CB",
rating: 4.9, totalJobs: 289,
experience: "14 years",
contact: "dispatch@volunteerescorts.example.com",
phone: "(615) 555-0956",
bio: "One of Tennessee's most experienced escort services. Specialize in transformer and heavy equipment moves throughout the Southeast."
}
];

193
public/js/nav.js Normal file
View File

@@ -0,0 +1,193 @@
// =============================================
// Shared Navigation, Banner, and Footer
// Include on every page via <script src="/js/nav.js">
// =============================================
function renderNav(activePage) {
const nav = document.getElementById('main-nav');
if (!nav) return;
const isActive = (id) => id === activePage;
const linkClass = (id) => isActive(id) ? 'text-amber-400 font-semibold' : 'text-gray-300 hover:text-white';
const dropLinkClass = (id) => isActive(id) ? 'bg-amber-50 text-amber-700 font-semibold' : 'text-slate-700 hover:bg-slate-50';
const regulationsActive = ['regulations','equipment','contacts','calendar'].includes(activePage);
const roadIntelActive = ['truckstops','bridges','weighstations','alerts'].includes(activePage);
nav.innerHTML = `
<nav class="bg-slate-900 text-white fixed top-0 w-full z-50 shadow-lg">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex items-center justify-between h-16">
<a href="/" class="flex items-center space-x-2 flex-shrink-0">
<span class="text-2xl">🚛</span>
<span class="text-xl font-bold text-amber-400 tracking-tight">PilotEdge</span>
</a>
<!-- Desktop Nav -->
<div class="hidden lg:flex items-center space-x-1">
<a href="/" class="${linkClass('home')} px-3 py-2 rounded-md text-sm transition-colors">Home</a>
<!-- Regulations Dropdown -->
<div class="relative group">
<button class="${regulationsActive ? 'text-amber-400 font-semibold' : 'text-gray-300 hover:text-white'} px-3 py-2 rounded-md text-sm transition-colors flex items-center gap-1">
Regulations
<svg class="w-3.5 h-3.5 opacity-60" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
</button>
<div class="absolute left-0 top-full pt-1 hidden group-hover:block" style="min-width:220px;">
<div class="bg-white rounded-xl shadow-xl border border-slate-200 py-2">
<a href="/pages/regulations.html" class="${dropLinkClass('regulations')} block px-4 py-2.5 text-sm transition-colors">
<div class="font-medium">State Regulations Map</div>
<div class="text-xs text-slate-400 mt-0.5">Permits & escort thresholds</div>
</a>
<a href="/pages/regulations.html#equipment" class="${dropLinkClass('equipment')} block px-4 py-2.5 text-sm transition-colors">
<div class="font-medium">Equipment Requirements</div>
<div class="text-xs text-slate-400 mt-0.5">Escort & carrier gear by state</div>
</a>
<a href="/pages/contacts.html" class="${dropLinkClass('contacts')} block px-4 py-2.5 text-sm transition-colors">
<div class="font-medium">DOT Contact Directory</div>
<div class="text-xs text-slate-400 mt-0.5">Permit office phone & email</div>
</a>
<a href="/pages/calendar.html" class="${dropLinkClass('calendar')} block px-4 py-2.5 text-sm transition-colors">
<div class="font-medium">Seasonal Calendar</div>
<div class="text-xs text-slate-400 mt-0.5">Restrictions & closures</div>
</a>
</div>
</div>
</div>
<!-- Road Intel Dropdown -->
<div class="relative group">
<button class="${roadIntelActive ? 'text-amber-400 font-semibold' : 'text-gray-300 hover:text-white'} px-3 py-2 rounded-md text-sm transition-colors flex items-center gap-1">
Road Intel
<svg class="w-3.5 h-3.5 opacity-60" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
</button>
<div class="absolute left-0 top-full pt-1 hidden group-hover:block" style="min-width:220px;">
<div class="bg-white rounded-xl shadow-xl border border-slate-200 py-2">
<a href="/pages/truckstops.html" class="${dropLinkClass('truckstops')} block px-4 py-2.5 text-sm transition-colors">
<div class="font-medium">Truck Stops & Parking</div>
<div class="text-xs text-slate-400 mt-0.5">Oversize-friendly locations</div>
</a>
<a href="/pages/bridges.html" class="${dropLinkClass('bridges')} block px-4 py-2.5 text-sm transition-colors">
<div class="font-medium">Bridge Clearances</div>
<div class="text-xs text-slate-400 mt-0.5">Height & width restrictions</div>
</a>
<a href="/pages/weighstations.html" class="${dropLinkClass('weighstations')} block px-4 py-2.5 text-sm transition-colors">
<div class="font-medium">Weigh Stations</div>
<div class="text-xs text-slate-400 mt-0.5">Live open/closed status</div>
</a>
<a href="/pages/alerts.html" class="${dropLinkClass('alerts')} block px-4 py-2.5 text-sm transition-colors">
<div class="font-medium">Route & Weather Alerts</div>
<div class="text-xs text-slate-400 mt-0.5">Closures, construction, wind</div>
</a>
</div>
</div>
</div>
<a href="/pages/loadboard.html" class="${linkClass('loadboard')} px-3 py-2 rounded-md text-sm transition-colors">Load Board</a>
<a href="/pages/locator.html" class="${linkClass('locator')} px-3 py-2 rounded-md text-sm transition-colors">Find Escorts</a>
<a href="/pages/documents.html" class="${linkClass('documents')} px-3 py-2 rounded-md text-sm transition-colors">Documents</a>
<a href="/pages/order.html" class="ml-2 bg-amber-500 hover:bg-amber-600 text-slate-900 font-bold px-4 py-2 rounded-lg transition-colors shadow-md hover:shadow-lg text-sm">
Request Service
</a>
</div>
<!-- Mobile menu button -->
<button onclick="toggleMobileMenu()" class="lg:hidden text-gray-300 hover:text-white p-2" aria-label="Toggle menu">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
</svg>
</button>
</div>
</div>
<!-- Mobile Menu -->
<div id="mobile-menu" class="lg:hidden hidden border-t border-slate-700 px-4 pb-4 max-h-[80vh] overflow-y-auto">
<a href="/" class="block py-2 px-3 mt-2 rounded ${isActive('home') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Home</a>
<div class="mt-2 mb-1 px-3 text-xs font-semibold text-slate-500 uppercase tracking-wider">Regulations</div>
<a href="/pages/regulations.html" class="block py-2 px-3 rounded ${isActive('regulations') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">State Regulations Map</a>
<a href="/pages/regulations.html#equipment" class="block py-2 px-3 rounded ${isActive('equipment') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Equipment Requirements</a>
<a href="/pages/contacts.html" class="block py-2 px-3 rounded ${isActive('contacts') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">DOT Contacts</a>
<a href="/pages/calendar.html" class="block py-2 px-3 rounded ${isActive('calendar') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Seasonal Calendar</a>
<div class="mt-2 mb-1 px-3 text-xs font-semibold text-slate-500 uppercase tracking-wider">Road Intel</div>
<a href="/pages/truckstops.html" class="block py-2 px-3 rounded ${isActive('truckstops') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Truck Stops & Parking</a>
<a href="/pages/bridges.html" class="block py-2 px-3 rounded ${isActive('bridges') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Bridge Clearances</a>
<a href="/pages/weighstations.html" class="block py-2 px-3 rounded ${isActive('weighstations') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Weigh Stations</a>
<a href="/pages/alerts.html" class="block py-2 px-3 rounded ${isActive('alerts') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Route & Weather Alerts</a>
<div class="mt-2 mb-1 px-3 text-xs font-semibold text-slate-500 uppercase tracking-wider">Services</div>
<a href="/pages/loadboard.html" class="block py-2 px-3 rounded ${isActive('loadboard') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Load Board</a>
<a href="/pages/locator.html" class="block py-2 px-3 rounded ${isActive('locator') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Find Escorts</a>
<a href="/pages/documents.html" class="block py-2 px-3 rounded ${isActive('documents') ? 'text-amber-400 bg-slate-800' : 'text-gray-300'}">Document Vault</a>
<a href="/pages/order.html" class="block py-2 px-3 mt-3 bg-amber-500 text-slate-900 font-bold rounded-lg text-center">Request Service</a>
</div>
</nav>
`;
}
function toggleMobileMenu() {
const menu = document.getElementById('mobile-menu');
if (menu) menu.classList.toggle('hidden');
}
function renderBanner() {
const banner = document.getElementById('poc-banner');
if (!banner) return;
banner.innerHTML = `
<div class="bg-amber-100 border-b border-amber-300 text-amber-900 text-center text-sm py-2 mt-16 px-4">
⚠️ <strong>POC / Demo</strong> — All regulation data is simulated for demonstration purposes. Verify with official state DOT sources before real-world use.
</div>
`;
}
function renderFooter() {
const footer = document.getElementById('main-footer');
if (!footer) return;
footer.innerHTML = `
<footer class="bg-slate-900 text-gray-400 mt-16">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<div class="grid md:grid-cols-4 gap-8">
<div>
<div class="flex items-center space-x-2 mb-4">
<span class="text-2xl">🚛</span>
<span class="text-lg font-bold text-amber-400">PilotEdge</span>
</div>
<p class="text-sm">Your complete resource for oversize and overdimensional load hauling. Built by industry professionals, for industry professionals.</p>
</div>
<div>
<h4 class="text-white font-semibold mb-3">Regulations</h4>
<ul class="space-y-2 text-sm">
<li><a href="/pages/regulations.html" class="hover:text-white transition-colors">State Regulations Map</a></li>
<li><a href="/pages/contacts.html" class="hover:text-white transition-colors">DOT Contact Directory</a></li>
<li><a href="/pages/calendar.html" class="hover:text-white transition-colors">Seasonal Calendar</a></li>
</ul>
</div>
<div>
<h4 class="text-white font-semibold mb-3">Road Intel</h4>
<ul class="space-y-2 text-sm">
<li><a href="/pages/truckstops.html" class="hover:text-white transition-colors">Truck Stops & Parking</a></li>
<li><a href="/pages/bridges.html" class="hover:text-white transition-colors">Bridge Clearances</a></li>
<li><a href="/pages/weighstations.html" class="hover:text-white transition-colors">Weigh Stations</a></li>
<li><a href="/pages/alerts.html" class="hover:text-white transition-colors">Route & Weather Alerts</a></li>
</ul>
</div>
<div>
<h4 class="text-white font-semibold mb-3">Services</h4>
<ul class="space-y-2 text-sm">
<li><a href="/pages/loadboard.html" class="hover:text-white transition-colors">Load Board</a></li>
<li><a href="/pages/locator.html" class="hover:text-white transition-colors">Find Escort Vehicles</a></li>
<li><a href="/pages/documents.html" class="hover:text-white transition-colors">Document Vault</a></li>
<li><a href="/pages/order.html" class="hover:text-white transition-colors">Request Escort Service</a></li>
</ul>
</div>
</div>
<div class="border-t border-slate-700 mt-8 pt-6 text-center text-sm">
&copy; 2026 PilotEdge. All rights reserved. | <span class="text-amber-400">V1 Proof of Concept</span>
</div>
</div>
</footer>
`;
}