---
title: "ROI Calculator"
id: "10468"
type: "page"
slug: "roi-calculator"
published_at: "2026-04-23T10:34:38+00:00"
modified_at: "2026-05-13T08:51:19+00:00"
url: "https://capow.energy/roi-calculator/"
markdown_url: "https://capow.energy/roi-calculator.md"
excerpt: "CaPow — ROI Calculator ROI Calculator Quantify your savings from Power-in-Motion It is advised to start with CaPow Uptime Calculator to find out by how much can we boost your operation 📸 Screenshot 📊 Export to Excel 💾 Save Results..."
---

CaPow — ROI CalculatorGreenfield: New Deployment

CaPowering your fleet even before launching your solution allows focusing on decreasing purchased number of robots, and all related expenses.

🏭

Fleet Size & Cost

100% uptime for 100% of your fleet allows achieving the same throughput with much less robots in your fleet

Work:Charge Ratio

Work:Charge Ratio defines critical parameters like extra robots in fleet or amount of needed chargers

Nominal Working Timehours

E.g. depleting from 80% battery to 30%

Charging Timehours

E.g. topping off from 30% to 80%

Work:Charge Ratio

6:1

Fleet Uptime

How much of your energy consumption is being delivered by CaPow

Enter Manually  Import from Uptime Calc

Fleet Uptime%

Select your saved **CaPow Uptime Calculator** file to auto-import Energy Coverage.

 📂 Select Uptime Calculator File

100%

CaPowered Work:Charge Ratio

∞

Required Fleet Sizeunits

Cost per robot$

Nominal Number of Chargersunits

Fleet Size ÷ Work:Charge Ratio

Cost per charger$

They're not so cheap, aren't they?

Fleet Size

Affected by charging downtime

12

CaPowered Potential Fleet Size

Reduced fleet, increased efficiency

10

Number of Required Chargers

CaPowered Fleet ÷ CaPowered Ratio

0

CaPowing your fleet can free up 2 robots

Yes, I will remove those from my existing fleet and utilize them somewhere else

   No, I will keep using them in order to boost productivity

CaPowing your fleet eliminates the need for 2 chargers

Yes, I will remove those chargers to free up floor space

   No, it's too much of a hassle. I'll keep them in place.

Count CapEx reduction as savings

CaPow Fleet Savings

Saved robots and chargers × cost

$110,000

📦

Floor Space Savings

Value of space freed up by removing floor chargers

Real-estate per chargerft²

How many ft² does a charger occupy

Cost of ft²$/ft²

How much does it cost to "lose" one ft²

Number of Chargers Savedunits

Nominal number of chargers - required chargers

CaPow Space Savings

ft² per charger × cost of ft² × chargers saved

$0

📈

Improved Yield

Freeing robots from the need to charge makes them available to pick up more missions

Added Operationsunits/shift

Average number of operations per shift, per robot

Yield per operation$

How much money does one operation gain you

Shifts per dayshifts

Days per weekdays

Solution Lifespanyears

Added Production Yield

How much extra juice did you get from those 2 robots

$312,000

🔋

Battery Implications

100% uptime allows your robots to use much smaller batteries, for much longer duration

  I don't want to spec down my batteries (but would still enjoy x2 on battery lifecycle)

Current Battery CapacityWh

Battery Price$

Current Battery Lifecycleyears

Reduced Spec Battery CapacityWh

100% uptime allows smaller battery capacity

Spec Down Battery Price$

Smaller batteries cost less

Improved Battery Lifecycleyears

Smaller DoD allows x2 battery lifecycle

Solution Lifespanyears

Automation solution duration, in years

CaPow Energy Savings

Traditional - CaPowered

Cost of Batteries- Traditional

Fleet size × battery price × number of batteries

$72,000

Cost of Batteries- CaPowered

CaPowered Fleet size × reduced battery price × number of batteries

$30,000

Net Battery Savings

$42,000

More robots in fleet, more batteries

💰

CaPow Overall Improvement

How much money did CaPowering your fleet actually gain you?

CaPow Fleet Savings

$110,000

CaPow Space Savings

$0

CaPow Battery Savings

$42,000

CaPow Overall Improvement over 5 years

$152,000

💡

CaPow Solution Pricing

So how much does it cost?

CaPow Overall Cost Duration  
Mirrors Solution Lifespanyears

Genesis Price  
100% uptime price, one time fee, per robot$

Genesis Energy Management Service cost  
energy monitoring fee, annual, per unit$

CaPow Overall Cost

(Genesis Price + Genesis EMS × 5 years) × CaPowered Fleet Size

$152,030

🏆

Bottom Line

Total project cost comparison over 5 years

Overall Project Cost Traditional

$682,000

Overall Project Cost CaPowered

$682,030

Net CaPow Savings

0%

ROI ⓘ

Day 1

Hover for full calculation

CaPow Operation Value

—

CaPow Costs

—

Net CaPow Margin

—

ROI

—

Hover for full calculation

 🤖

The CaPow Effect

Robots Saved2 robots

Chargers Eliminated2 chargers

Floor Space Freed130 ft²

Battery Swaps Avoided12 swaps

📊

Break-Even Analysis

Genesis Break Even Price$11,261

At this Genesis PPU, project breaks even

Current Genesis Price$11,263

GEMS Annual %7%

Margin$-2

💵

Cost Breakdown

Gross CaPow Savings$152,000

Net CaPow Savings$-30

Net CaPow Savings %0%

ROIDay 1

 🤖

The CaPow Effect

Robots Saved—

Chargers Eliminated—

Floor Space Freed—

Added Production Yield—

📊

Break-Even Analysis

Genesis Break Even Price—

At this Genesis PPU, project breaks even

Current Genesis Price—

GEMS Annual %7%

Margin—

💵

Cost Breakdown

Gross CaPow Savings—

Net CaPow Savings—

Net CaPow Savings %—

ROI—

|  | Traditional | CaPowered |
| --- | --- | --- |
| Robots | 12 × $50,000 | 10 × $50,000 |
| Chargers | 2 × $5,000 | — |
| Floor space | 2 × 65ft² × $0/ft² | — |
| Batteries (initial) | 12 × $3,000 | 10 × $3,000 |
| Genesis PPU | — | 10 × $11,263 |
| Genesis EMS yr 1 | — | 10 × $788 |
| Day 0 Total | $646,000 | $650,510 |
| Over 5 years |  |  |
| Battery replacements (×1) | 1 × 12 × $3,000 | 0 × 10 × $3,000 |
| Genesis EMS yr 2–5 | — | 10 × $788 × 4yr |
| Overall 5yr Total | $682,000 | $682,030 |

Day 0 balance: −$4,510 ❌

Overall 5yr saving: −$30 ❌

Yr ${y}: EMS ${tf(annualEMSCost)}

${yieldActive ? tf(yieldThisYear) : '—'}

${tf(annualEMSCost)}

`; } const tradGrandTotal = savingsDay0 + annualYield * lifespanYrs; const capowGrandTotal = capowDay0Brown + annualEMSCost * (lifespanYrs - 1); const grandBottomLine = tradGrandTotal - capowGrandTotal; brownTooltip.innerHTML = ` Savings Day 0

Fleet savings

Genesis PPU: ${roiFleetSize} × ${tf(capowPPU)}

${tf(capowFleetSavings)}

${tf(roiFleetSize * capowPPU)}

Space savings

Genesis EMS yr 1: ${roiFleetSize} × ${tf(genesisEMS)}

${tf(spaceSavingsForOverall)}

${tf(roiFleetSize * genesisEMS)}

Total

Total

${tf(savingsDay0)}

${tf(capowDay0Brown)}

Day 0 balance: ${sign(day0)}${tf(day0)} ${day0 >= 0 ? '✅' : '❌'}

Year 1

${yieldActive ? `Added Production Yield` : '—'}

No additional EMS

${yieldActive ? tf(annualYield) : '—'}

—

 ${lifespanYrs > 1 ? ` Year 2 – ${lifespanYrs} Recurring

${yearRows} Recurring Total

Recurring Total

${yieldActive ? tf(annualYield * (lifespanYrs - 1)) : '—'}

${tf(annualEMSCost * (lifespanYrs - 1))}

` : ''} ${lifespanYrs}yr Grand Total

${lifespanYrs}yr Grand Total

${tf(tradGrandTotal)}

${tf(capowGrandTotal)}

Bottom line: ${sign(grandBottomLine)}${tf(grandBottomLine)} ${grandBottomLine >= 0 ? '✅' : '❌'}

`; } } else { if (bottomLineGreenfield) bottomLineGreenfield.style.display = ''; if (bottomLineBrownfield) bottomLineBrownfield.style.display = 'none'; if (bottomLineSubtitle) bottomLineSubtitle.textContent = `Total project cost comparison over ${capowCostDuration} year${capowCostDuration !== 1 ? 's' : ''}`; const fleetC = capoweredFleet !== null ? capoweredFleet : robotsNominal; bottomLineTradVal = (robotsActual * robotCost) + (chargersRequired * chargerCostFleet) + tradSpaceCost + batteryCostTraditional; bottomLineCapowVal = (fleetC * robotCost) + (capoweredChargers * chargerCostFleet) + capowSpaceCost + batteryCostCapow + capowOverallCostVal; const bottomLineNetPct = bottomLineTradVal > 0 ? (1 - bottomLineCapowVal / bottomLineTradVal) * 100 : 0; const blTrad = document.getElementById('bottomLineTrad'); const blCapow = document.getElementById('bottomLineCapow'); const blPct = document.getElementById('bottomLineNetPct'); if (blTrad) blTrad.textContent = fmt(bottomLineTradVal); if (blCapow) blCapow.textContent = fmt(bottomLineCapowVal); if (blPct) { blPct.textContent = Math.round(bottomLineNetPct) + '%'; blPct.style.color = bottomLineNetPct >= 0 ? 'var(--green)' : 'var(--red)'; } // Greenfield ROI simulation // Day 0: initial purchase only (1x batteries, Genesis PPU — no EMS yet, no replacements) const roiElG = document.getElementById('bottomLineROIGreen'); const roiSubG = document.getElementById('bottomLineROISubGreen'); const gLifespanMonths = capowCostDuration * 12; const tradDay0 = (robotsActual * robotCost) + (chargersRequired * chargerCostFleet) + tradSpaceCost + (robotsActual * batteryPriceVal); // 1x initial batteries only const capowDay0 = (fleetC * robotCost) + (capoweredChargers * chargerCostFleet) + capowSpaceCost + (fleetC * specDownPriceVal) // 1x spec-down batteries only + (fleetC * capowPPU) // Genesis PPU + (fleetC * genesisEMS); // EMS year 1 const gDay0 = tradDay0 - capowDay0; // Simulate year by year: at each year-end deduct EMS, add/deduct battery replacements when due // ROI is only declared when cumulative goes positive AND stays positive through end of lifespan let gRoiMonths = null; // Build full year-by-year cumulative array first const yearlyBalance = [gDay0]; for (let y = 1; y <= capowCostDuration; y++) { let bal = yearlyBalance[y - 1]; if (y >= 2) bal -= fleetC * genesisEMS; if (batteryLifecycleVal > 0 && y % batteryLifecycleVal === 0) bal += robotsActual * batteryPriceVal; if (improvedLifecycleVal > 0 && y % improvedLifecycleVal === 0) bal -= fleetC * specDownPriceVal; yearlyBalance[y] = bal; } // Find first year (0 = Day 0) where cumulative goes positive AND stays positive through end for (let y = 0; y <= capowCostDuration; y++) { if (yearlyBalance[y] >= 0) { const staysPositive = yearlyBalance.slice(y).every(b => b >= 0); if (staysPositive) { gRoiMonths = y * 12; break; } } } if (roiElG) { if (gRoiMonths === null) { roiElG.textContent = '—'; roiElG.style.color = 'var(--muted)'; } else if (gRoiMonths === 0) { roiElG.textContent = 'Day 1'; roiElG.style.color = 'var(--green)'; } else { roiElG.textContent = gRoiMonths + ' mo'; roiElG.style.color = gRoiMonths <= gLifespanMonths ? 'var(--green)' : 'var(--red)'; } } if (roiSubG) roiSubG.textContent = 'Break-even point'; // Populate inline breakdown (Greenfield) const tooltip = document.getElementById('roiGreenTooltip'); if (tooltip) { const sym = currentCurrency === 'EUR' ? '€' : '$'; const tf = v => sym + Math.round(Math.abs(v)).toLocaleString(); const sign = v => v >= 0 ? '+' : '−'; const unitLbl = currentUnit === 'm' ? 'm²' : 'ft²'; const tradRobotCost = robotsActual * robotCost; const tradChargerCost = chargersRequired * chargerCostFleet; const tradBatteryCost = robotsActual * batteryPriceVal; const capowRobotCost = fleetC * robotCost; const capowChargerCost = capoweredChargers * chargerCostFleet; const capowBatteryCost = fleetC * specDownPriceVal; const capowGenesisCost = fleetC * capowPPU; const capowEMSYr1 = fleetC * genesisEMS; const capowTotal = capowDay0; // EMS yr1 already included in capowDay0 const col = (label, val, isBold) => `${label}

${val}

`; tooltip.innerHTML = ` Traditional Day 0

CaPowered Day 0

Robots: ${robotsActual} × ${tf(robotCost)}

Robots: ${fleetC} × ${tf(robotCost)}

${tf(tradRobotCost)}

${tf(capowRobotCost)}

Chargers: ${chargersRequired} × ${tf(chargerCostFleet)}

Chargers: ${capoweredChargers} × ${tf(chargerCostFleet)}

${tf(tradChargerCost)}

${tf(capowChargerCost)}

Floor space

Floor space

${tf(tradSpaceCost)}

${tf(capowSpaceCost)}

Batteries: ${robotsActual} × ${tf(batteryPriceVal)}

Batteries: ${fleetC} × ${tf(specDownPriceVal)}

${tf(tradBatteryCost)}

${tf(capowBatteryCost)}

Genesis PPU: ${fleetC} × ${tf(capowPPU)}

${tf(capowGenesisCost)}

Genesis EMS yr 1: ${fleetC} × ${tf(genesisEMS)}

${tf(capowEMSYr1)}

Total

Total

${tf(tradDay0)}

${tf(capowTotal)}

Day 0 balance: ${sign(gDay0)}${tf(gDay0)} ${gDay0 >= 0 ? '✅' : '❌'} ${gDay0 >= 0 ? 'Savings exceed CaPow cost from day one' : ''}

 ${capowCostDuration > 1 ? (() => { // Build year-by-year rows for Yr 2 to lifespan const tradBattReplacements = batteryLifecycleVal > 0 ? Math.floor(capowCostDuration / batteryLifecycleVal) : 0; const capowBattReplacements = improvedLifecycleVal > 0 ? Math.floor(capowCostDuration / improvedLifecycleVal) : 0; const tradRecurring = tradBattReplacements * robotsActual * batteryPriceVal; const capowEMSTotal = fleetC * genesisEMS * (capowCostDuration - 1); const capowBattTotal = capowBattReplacements * fleetC * specDownPriceVal; const tradGrandTotal = tradDay0 + tradRecurring; const capowGrandTotal = capowTotal + capowEMSTotal + capowBattTotal; const bottomLine = tradGrandTotal - capowGrandTotal; let yearRows = ''; for (let y = 2; y <= capowCostDuration; y++) { const tradBattThisYear = (batteryLifecycleVal > 0 && y % batteryLifecycleVal === 0) ? robotsActual * batteryPriceVal : 0; const capowEMSThisYear = fleetC * genesisEMS; const capowBattThisYear = (improvedLifecycleVal > 0 && y % improvedLifecycleVal === 0) ? fleetC * specDownPriceVal : 0; const tradYearTotal = tradBattThisYear; const capowYearTotal = capowEMSThisYear + capowBattThisYear; yearRows += ` Yr ${y}: ${tradBattThisYear > 0 ? `Battery repl. ${tf(tradBattThisYear)}` : '—'}

Yr ${y}: EMS ${tf(capowEMSThisYear)}${capowBattThisYear > 0 ? ` + Batt repl. ${tf(capowBattThisYear)}` : ''}

${tradYearTotal > 0 ? tf(tradYearTotal) : '—'}

${tf(capowYearTotal)}

`; } return ` Year 2 – ${capowCostDuration} Recurring Costs

${yearRows} Recurring Total

Recurring Total

${tf(tradRecurring)}

${tf(capowEMSTotal + capowBattTotal)}

${capowCostDuration}yr Grand Total

${capowCostDuration}yr Grand Total

${tf(tradGrandTotal)}

${tf(capowGrandTotal)}

Bottom line: ${sign(bottomLine)}${tf(bottomLine)} ${bottomLine >= 0 ? '✅' : '❌'}

`; })() : ''}

`; } } // Swap sidebars based on mode const sbGreen = document.getElementById('sidebarGreenfield'); const sbBrown = document.getElementById('sidebarBrownfield'); if (sbGreen) sbGreen.style.display = isBrownfield ? 'none' : ''; if (sbBrown) sbBrown.style.display = isBrownfield ? '' : 'none'; // Update results panel — Greenfield only, never touched in Brownfield mode if (!isBrownfield) { // Genesis Break-Even Price: constant w.r.t. Genesis Price and EMS const capowFleetForBE = capoweredFleet !== null ? capoweredFleet : robotsNominal; const capowWithoutAnyCaPow = (capowFleetForBE * robotCost) + (capoweredChargers * chargerCostFleet) + capowSpaceCost + batteryCostCapow; const emsRatio = capowPPU > 0 ? genesisEMS / capowPPU : 0.07; const breakEvenPPU = capowFleetForBE > 0 ? (bottomLineTradVal - capowWithoutAnyCaPow) / capowFleetForBE / (1 + capowCostDuration * emsRatio) : 0; set('breakEvenPPU', breakEvenPPU, 0); document.getElementById('breakEvenDisplay').textContent = fmt(breakEvenPPU); document.getElementById('actualPPUDisplay').textContent = fmt(capowPPU); const cpuLabel = document.getElementById('label-capowCostPerUnit'); if (cpuLabel) cpuLabel.textContent = 'Current Genesis Price'; const gemsPctEl = document.getElementById('gemsPctDisplay'); if (gemsPctEl) gemsPctEl.textContent = capowPPU > 0 ? Math.round(genesisEMS / capowPPU * 100) + '%' : '—'; const ppuMargin = breakEvenPPU - capowPPU; const ppuEl = document.getElementById('ppuMarginDisplay'); ppuEl.textContent = fmt(ppuMargin); ppuEl.className = 'result-value ' + (ppuMargin >= 0 ? 'green' : 'red'); document.getElementById('robotsSaved').textContent = robotsSaved + ' robots'; document.getElementById('chargersElim').textContent = chargersEliminated + ' chargers'; const floorSpaceFreedEl = document.getElementById('floorSpaceFreed'); if (floorSpaceFreedEl) { const sqftPerCharger = parseFloat(document.getElementById('skusPerCharger').value) || 0; const floorSpaceTotal = sqftPerCharger * chargersEliminated; const unitLabel = currentUnit === 'm' ? 'm²' : 'ft²'; floorSpaceFreedEl.textContent = floorSpaceTotal > 0 ? floorSpaceTotal.toLocaleString() + ' ' + unitLabel : '0 ' + unitLabel; } const tradSwaps = batteryLifecycleVal > 0 ? Math.floor(solutionLifespan / batteryLifecycleVal) * robotsActual : 0; const capowSwaps = improvedLifecycleVal > 0 ? Math.floor(solutionLifespan / improvedLifecycleVal) * (capoweredFleet !== null ? capoweredFleet : robotsNominal) : 0; const swapEvasions = tradSwaps - capowSwaps; const swapEl = document.getElementById('batterySwapEvasions'); if (swapEl) swapEl.textContent = swapEvasions > 0 ? swapEvasions + ' swaps' : '0 swaps'; const netSavingsEl = document.getElementById('netSavingsRow'); netSavingsEl.textContent = fmt(netSavings); netSavingsEl.className = 'result-value ' + (netSavings >= 0 ? 'green' : 'red'); const grossEl = document.getElementById('grossCapowSavingsSidebar'); if (grossEl) { grossEl.textContent = fmt(overallTotal); grossEl.className = 'result-value ' + (overallTotal >= 0 ? 'green' : 'red'); } const netSavingsPctVal = bottomLineTradVal > 0 ? (1 - bottomLineCapowVal / bottomLineTradVal) * 100 : 0; const netSavingsPctEl = document.getElementById('netSavingsPct'); netSavingsPctEl.textContent = Math.round(netSavingsPctVal) + '%'; netSavingsPctEl.className = 'result-value ' + (netSavingsPctVal >= 0 ? 'green' : 'red'); const roiSidebarEl = document.getElementById('roiSidebar'); if (roiSidebarEl) { const roiSrc = document.getElementById('bottomLineROIGreen'); roiSidebarEl.textContent = roiSrc ? roiSrc.textContent : '—'; roiSidebarEl.className = 'result-value green'; } } } // Export to Excel function exportToExcel() { try { if (typeof XLSX === 'undefined') { alert('Excel library still loading. Try again in a moment.'); return; } const projectName = document.getElementById('projectName').value.trim() || 'Untitled Project'; const dateStr = new Date().toISOString().split('T')[0]; const sym = currentCurrency === 'EUR' ? '\u20ac' : '$'; const val = id => { const el = document.getElementById(id); return el ? (parseFloat(el.value) || 0) : 0; }; const txt = id => { const el = document.getElementById(id); return el ? el.textContent.trim() : '\u2014'; }; const data = [ ['CaPow ROI Calculator'], ['Project:', projectName], ['Date:', dateStr], [], ['===== ROBOT OPERATIONS ====='], ['Nominal Working Time (h)', val('nominalWorkTime')], ['Charging Time (h)', val('chargingTime')], ['Work:Charge Ratio', txt('workChargeRatio')], [], ['===== FLEET SIZE ====='], ['Required Fleet Size (Nominal)', val('robotsNominal')], ['Traditional Fleet Size', txt('robotsActualDisplay')], ['CaPowered Fleet Size', txt('capoweredFleetDisplay')], ['Robots Saved', txt('robotsSaved')], ['Robot Cost per Unit (' + sym + ')', val('robotCost')], ['Robot Savings (' + sym + ')', txt('robotSavings')], ['Chargers Required', val('chargersRequired')], ['Cost per Charger (' + sym + ')', val('chargerCostFleet')], ['Chargers Eliminated', txt('chargersElim')], ['CaPow Fleet Savings (' + sym + ')', txt('capowFleetSavingsDisplay')], [], ['===== CaPow SOLUTION ====='], ['Genesis Price (' + sym + ')', val('capowPPU')], ['Genesis EMS (' + sym + ')', val('genesisEMS')], ['Genesis Break Even Price (' + sym + ')', txt('breakEvenDisplay')], ['Genesis Price (' + sym + ')', txt('actualPPUDisplay')], ['Price Margin (' + sym + ')', txt('ppuMarginDisplay')], [], ['===== NET RESULT ====='], ['Traditional TCO (' + sym + ')', txt('traditionalTCO')], ['Gross CaPow Savings (' + sym + ')', txt('grossSavings')], ['CaPow Charges (' + sym + ')', txt('capowCharges')], ['Lost Yield (' + sym + ')', txt('lostYield')], ['Net CaPow Savings (' + sym + ')', txt('verdictValue')], ]; const wb = XLSX.utils.book_new(); const ws = XLSX.utils.aoa_to_sheet(data); ws['!cols'] = [{ wch: 38 }, { wch: 20 }]; XLSX.utils.book_append_sheet(wb, ws, 'ROI Report'); const wbOut = XLSX.write(wb, { bookType: 'xlsx', type: 'array' }); const blob = new Blob([wbOut], { type: 'application/octet-stream' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = projectName + '_ROI_' + dateStr + '.xlsx'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } catch(e) { alert('Export failed: ' + e.message); } } // Screenshot async function takeScreenshot() { const projectName = document.getElementById('projectName').value.trim() || 'Untitled Project'; const dateStr = new Date().toISOString().split('T')[0]; try { if (typeof html2canvas === 'undefined') { alert('Screenshot library still loading. Try again in a moment.'); return; } await document.fonts.ready; const prevScrollY = window.scrollY; window.scrollTo(0, 0); await new Promise(r => setTimeout(r, 300)); const canvas = await html2canvas(document.documentElement, { backgroundColor: '#F9FAFB', scale: 2, logging: false, useCORS: true, allowTaint: true, scrollY: 0, scrollX: 0, windowWidth: document.documentElement.scrollWidth, windowHeight: document.documentElement.scrollHeight, width: document.documentElement.scrollWidth, height: document.documentElement.scrollHeight, onclone: (clonedDoc) => { const rp = clonedDoc.querySelector('.results-panel'); if (rp) { rp.style.position='relative'; rp.style.top='auto'; rp.style.maxHeight='none'; rp.style.overflow='visible'; } } }); window.scrollTo(0, prevScrollY); const link = document.createElement('a'); link.download = `${projectName}_ROI_${dateStr}.png`; link.href = canvas.toDataURL('image/png'); link.click(); } catch (e) { alert('Screenshot failed: ' + e.message); } } // Init setMultiplierMode('manual'); setProjectType('brownfield'); updateSpecDownPrice(); onFleetRemovalChange(); onChargerRemovalChange(); calculate();

## To view the content, please fill out the form below or enter a password.

EnterWrong password, try again.
