<!doctype html>

<html lang="en">

<head>

<meta charset="utf-8" />

<meta name="viewport" content="width=device-width,initial-scale=1" />

<title>Fix & Flip SFH Proforma — PCG v1.9.5</title>

<style>

  :root{

    --bg:#f7f9fc; --card:#ffffff; --ink:#111827; --sub:#374151; --muted:#6b7280;

    --border:#e5e7eb; --accent:#0ea5e9; --input:#f8fafc; --chip:#eef2f7;

  }

  *{box-sizing:border-box}

  html,body{margin:0;background:var(--bg);color:var(--ink);font:14px/1.5 system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif}

  .wrap{max-width:1100px;margin:18px auto 64px;padding:0 12px}

  header{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:12px;flex-wrap:wrap}

  .brand{display:flex;align-items:center;gap:10px}

  .brand img{height:34px;border-radius:6px}

  .brand svg{height:34px}

  .title{font-weight:700}

  .toolbar{display:flex;gap:8px;flex-wrap:wrap}

  button{background:#fff;border:1px solid var(--border);border-radius:8px;padding:10px 12px;font-weight:600;cursor:pointer}

  button:hover{border-color:var(--accent);box-shadow:0 0 0 3px rgba(14,165,233,.12)}

  .grid{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:10px}

  .card{background:var(--card);border:1px solid var(--border);border-radius:12px;padding:14px;box-shadow:0 1px 2px rgba(0,0,0,.03)}

  .span-6{grid-column:span 6}.span-12{grid-column:span 12}

  h2{font-size:13px;margin:0 0 8px;color:var(--sub);text-transform:uppercase;letter-spacing:.08em}

  label{display:block;font-size:12px;color:var(--muted);margin:6px 0 6px}

  input,select{width:100%;background:var(--input);color:var(--ink);border:1px solid var(--border);border-radius:8px;padding:10px 12px;font-size:14px;outline:none}

  input:focus,select:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(14,165,233,.15);background:#fff}

  input::placeholder{color:#c1c9d3}

  .row{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}

  .inline{display:flex;align-items:center;gap:8px}

  .left-toggle{display:flex;align-items:center;gap:8px;margin:6px 0}

  .note{font-size:12px;color:var(--muted)}

  .chip{display:inline-block;background:var(--chip);border:1px solid var(--border);border-radius:999px;padding:2px 8px;font-size:12px;min-width:84px;text-align:right}

  .outputs{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}

  .metric{background:var(--input);border:1px solid var(--border);border-radius:12px;padding:12px}

  .metric h3{margin:0 0 6px;font-size:12px;color:var(--sub);text-transform:uppercase;letter-spacing:.08em}

  .metric .val{font-size:20px;font-weight:700}

  .calc{font-size:12px;color:#6b7280;margin-top:6px}

  .calc b{font-weight:700}

  /* PDF: force exactly 2 pages */

  @page{size:Letter;margin:0.5in}

  .page{margin-bottom:10px}

  .page.p1 .grid{grid-template-columns:repeat(12,minmax(0,1fr))}

  .p1 .span-6{grid-column:span 6}

  @media print{

    body{background:#fff}

    header .toolbar,.hide-print{display:none!important}

    .wrap{margin:0 auto;padding:0}

    .page{page-break-after:always}

    .page:last-child{page-break-after:auto}

    .p1 .grid{grid-template-columns:repeat(12,minmax(0,1fr)) !important}

    .span-6,.span-12{break-inside:avoid;page-break-inside:avoid}

    .card{break-inside:avoid;page-break-inside:avoid;box-shadow:none;border-color:#ddd;margin-bottom:6px}

    .outputs .metric{break-inside:avoid;page-break-inside:avoid}

    .metric .val{font-size:18px}

  }

  @media(max-width:880px){.grid{grid-template-columns:repeat(6,minmax(0,1fr))}.span-6{grid-column:span 6}.outputs{grid-template-columns:repeat(2,minmax(0,1fr))}}

  @media(max-width:540px){.grid{grid-template-columns:repeat(2,minmax(0,1fr))}.span-6,.span-12{grid-column:span 2}.outputs{grid-template-columns:1fr}}

</style>

</head>

<body>

  <div class="wrap">

    <header>

      <div class="brand">

        <!-- Tiny embedded SVG logo (fallback). Use Upload Logo to swap your real logo -->

        <svg viewBox="0 0 120 36" xmlns="http://www.w3.org/2000/svg" aria-label="PCG">

          <rect x="0" y="0" width="120" height="36" rx="6" fill="#0ea5e9"/>

          <text x="60" y="24" text-anchor="middle" font-family="Inter, system-ui, sans-serif" font-size="18" fill="#fff" font-weight="700">PCG</text>

        </svg>

        <div class="title">Fix & Flip SFH Proforma</div>

      </div>

      <div class="toolbar">

        <input id="logoFile" type="file" accept=".png,.jpg,.jpeg,.webp" class="hide-print" style="display:none" />

        <button id="btnLogo" class="hide-print">Upload Logo</button>

        <button id="btnPDF" class="hide-print">Export PDF</button>

        <button id="btnSave" class="hide-print">Save Scenario</button>

        <button id="btnLoad" class="hide-print">Load Scenario</button>

      </div>

    </header>


    <!-- PAGE 1: all inputs compact -->

    <section class="page p1">

      <div class="grid">

        <div class="card span-6">

          <h2>Property Info</h2>

          <label>Address, City, Zip</label>

          <input id="address" />

          <div class="row">

            <div><label>Asking Price ($)</label><input data-currency id="askingPrice" /></div>

            <div><label>Acquisition Price ($)</label><input data-currency id="acqPrice" /></div>

          </div>

          <div class="row">

            <div><label>Acquisition Date (MM/DD/YYYY)</label><input id="closingDate" type="date" /></div>

            <div>

              <label>Monthly Holding Cost ($) <span class="note">(auto from annuals; toggle to override)</span></label>

              <input id="holdingPerMo" data-currency placeholder="auto" disabled />

              <div class="left-toggle">

                <input type="checkbox" id="overrideHold" />

                <span class="note">Override monthly holding cost</span>

              </div>

            </div>

          </div>

          <div class="row">

            <div><label>Property Tax (Annual, $)</label><input id="taxAnnual" data-currency /></div>

            <div><label>Insurance (Annual, $)</label><input id="insAnnual" data-currency /></div>

          </div>

          <div class="row">

            <div><label>Misc. (Annual, $)</label><input id="miscAnnual" data-currency /></div>

            <div></div>

          </div>

          <div class="row">

            <div><label>Current Bed / Bath <span class="note">(e.g., 4/2)</span></label><input id="currentBB" /></div>

            <div><label>New Bed / Bath <span class="note">(e.g., 5/3)</span></label><input id="newBB" /></div>

          </div>

          <div class="row">

            <div><label>Garage Spaces</label><input id="garages" /></div>

            <div><label>Lot Size (Sq Ft)</label><input id="lot" data-integer /></div>

          </div>

          <div class="row">

            <div><label>Current Home Size (Sq Ft)</label><input id="curSqft" data-integer /></div>

            <div><label>New Home Size (Sq Ft)</label><input id="newSqft" data-integer /></div>

          </div>

        </div>


        <div class="card span-6">

          <h2>Timeline</h2>

          <div class="row">

            <div><label>Permits (months)</label><input id="mPermits" data-integer /></div>

            <div><label>Construction (months)</label><input id="mConst" data-integer /></div>

          </div>

          <div class="row">

            <div><label>Marketing (months)</label><input id="mMkt" data-integer /></div>

            <div><label>Total Months (auto)</label><input id="mTotal" disabled /></div>

          </div>

          <div class="row">

            <div><label>Exit Date (auto)</label><input id="exitDateAuto" disabled /></div>

            <div></div>

          </div>


          <h2>Construction & Soft</h2>

          <div class="row">

            <div><label>Construction $ / Sq Ft</label><input id="costPerSqft" data-currency /></div>

            <div><label>Contingency % (default 5)</label><input id="contPct" data-percent placeholder="5" /></div>

          </div>

          <div class="row">

            <div><label>Architect / Engineer ($)</label><input id="archFee" data-currency /></div>

            <div><label>Permits ($)</label><input id="permits" data-currency /></div>

          </div>

          <div class="row">

            <div><label>Legal Fees ($)</label><input id="legal" data-currency /></div>

            <div><label>Optional Stabilized Annual NOI ($)</label><input id="noiy" data-currency /></div>

          </div>

        </div>


        <div class="card span-6">

          <h2>Financing</h2>

          <div class="left-toggle">

            <input type="checkbox" id="cashDeal" />

            <span class="note">Cash Deal (zero out debt, fees, interest)</span>

          </div>

          <div class="row">

            <div><label>Acquisition Interest Rate %</label><input id="acqRate" data-percent placeholder="" /></div>

            <div><label>Construction Interest Rate %</label><input id="conRate" data-percent placeholder="" /></div>

          </div>

          <div class="row">

            <div><label>Bank Fee %</label><div class="inline"><input id="bankFeePct" data-percent placeholder="1" /><span class="chip" id="bankFee$">—</span></div></div>

            <div><label>Loan Broker Fee %</label><div class="inline"><input id="loanFeePct" data-percent placeholder="1" /><span class="chip" id="loanFee$">—</span></div></div>

          </div>

          <div class="row">

            <div><label>Acquisition Closing Costs %</label><div class="inline"><input id="acqClosePct" data-percent placeholder="2" /><span class="chip" id="acqClose$">—</span></div></div>

            <div><label>LTV Cap %</label><input id="ltv" data-percent placeholder="75" /></div>

          </div>

          <div class="row">

            <div><label>LTC Cap %</label><input id="ltc" data-percent placeholder="80" /></div>

            <div><label>Draw Schedule</label>

              <select id="drawMode">

                <option value="simple">Simple (50% avg during construction)</option>

                <option value="full">Full Balance entire period</option>

              </select>

            </div>

          </div>

        </div>


        <div class="card span-6">

          <h2>Capital Stack</h2>

          <div class="row">

            <div><label>Sponsor Capital ($)</label><input id="sponCap" data-currency /></div>

            <div><label>Sponsor Equity %</label><input id="sponPct" data-percent placeholder="50" /></div>

          </div>

          <div class="row">

            <div><label>LP Capital ($)</label><input id="lpCap" data-currency /></div>

            <div><label>LP Equity %</label><input id="lpPct" data-percent placeholder="50" /></div>

          </div>

          <div class="row">

            <div><label>Total Capital Needed (auto)</label><input id="totalCapNeeded" disabled /></div>

            <div><label>LP Preferred Return %</label><input id="lpPref" data-percent placeholder="0" /></div>

          </div>

        </div>


        <div class="card span-6">

          <h2>Exit</h2>

          <div class="row">

            <div><label>Exit Price ($)</label><input id="exitPrice" data-currency /></div>

            <div><label>Sale Broker %</label><input id="saleBrokerPct" data-percent placeholder="5" /></div>

          </div>

          <div class="row">

            <div><label>Sale Closing %</label><input id="saleClosePct" data-percent placeholder="2" /></div>

            <div><label>Cost of Sale (auto)</label><input id="saleCost" disabled /></div>

          </div>

        </div>

      </div>

    </section>


    <!-- PAGE 2: key outputs -->

    <section class="page p2">

      <div class="grid">

        <div class="card span-12">

          <h2>Key Outputs</h2>

          <div class="outputs">

            <div class="metric"><h3>% Discount</h3><div class="val" id="discount">—</div><div class="calc"><b>Calculation:</b> (Asking − Acquisition) ÷ Asking.</div></div>

            <div class="metric"><h3>Loan Amount</h3><div class="val" id="loanAmt">—</div><div class="calc"><b>Calculation:</b> min(LTV×Total Cost, LTC×Total Cost) with financing factor.</div></div>

            <div class="metric"><h3>Interest Reserve</h3><div class="val" id="intRes">—</div><div class="calc"><b>Calculation:</b> Loan × Rate × (weighted draw months ÷ 12).</div></div>

            <div class="metric"><h3>Total Hard Costs</h3><div class="val" id="hardCosts">—</div><div class="calc"><b>Calculation:</b> (New Sq Ft × $/Sq Ft) + Contingency.</div></div>

            <div class="metric"><h3>Total Soft Costs</h3><div class="val" id="softCosts">—</div><div class="calc"><b>Calculation:</b> Architect + Permits + Legal.</div></div>

            <div class="metric"><h3>Total Project Cost</h3><div class="val" id="projCost">—</div><div class="calc"><b>Calculation:</b> Acquisition + Acquisition Closing + Hard + Contingency + Soft + Holding + Interest + Bank + Broker.</div></div>

            <div class="metric"><h3>Profit $</h3><div class="val" id="profit">—</div><div class="calc"><b>Calculation:</b> Exit Net − Total Project Cost.</div></div>

            <div class="metric"><h3>Total Time Held</h3><div class="val" id="timeHeld">—</div><div class="calc"><b>Calculation:</b> Permits + Construction + Marketing (months).</div></div>

            <div class="metric"><h3>Unlevered CoC</h3><div class="val" id="uCoC">—</div><div class="calc"><b>Calculation:</b> (Exit Net − Unlevered Equity) ÷ Unlevered Equity.</div></div>

            <div class="metric"><h3>Levered CoC</h3><div class="val" id="lCoC">—</div><div class="calc"><b>Calculation:</b> Profit ÷ Equity Needed.</div></div>

            <div class="metric"><h3>IRR (Annualized)</h3><div class="val" id="irr">—</div><div class="calc"><b>Calculation:</b> (Equity Return ÷ Equity)^(12/Months) − 1.</div></div>

            <div class="metric"><h3>Equity Multiple</h3><div class="val" id="em">—</div><div class="calc"><b>Calculation:</b> (Exit Net − Debt) ÷ Equity.</div></div>

            <div class="metric"><h3>LP CoC</h3><div class="val" id="lpCoC">—</div><div class="calc"><b>Calculation:</b> LP Distribution ÷ LP Capital. (Pref accrual first; remainder by LP%.)</div></div>

            <div class="metric"><h3>Break‑Even Sale</h3><div class="val" id="breakeven">—</div><div class="calc"><b>Calculation:</b> Project Cost ÷ (1 − Sale Cost %).</div></div>

            <div class="metric"><h3>Margin on Cost</h3><div class="val" id="moc">—</div><div class="calc"><b>Calculation:</b> Profit ÷ Project Cost.</div></div>

            <div class="metric"><h3>Yield on Cost</h3><div class="val" id="yoc">—</div><div class="calc"><b>Calculation:</b> NOI ÷ Project Cost (if NOI provided).</div></div>

          </div>

          <div class="note" style="margin-top:10px">

            LEGAL NOTICE: This document is a pro forma analysis and is intended for informational purposes only. It does not constitute a guarantee of results, an offer to sell or solicit an offer to buy securities, or a commitment to lend. Assumptions are estimates and subject to change. Actual results may differ materially.

          </div>

        </div>

      </div>

    </section>

  </div>


<script>

  const $ = id => document.getElementById(id);

  const raw = new Map();

  const onlyDigits = s => (s||'').replace(/[^0-9.\\-]/g,'');

  const parseCurrency = id => { const s = onlyDigits(raw.get(id) ?? $(id).value); const n = parseFloat(s); return isFinite(n) ? n : 0; };

  const parsePercent  = (id, d=0) => { const s = onlyDigits(raw.get(id) ?? $(id).value); if(!s) return d/100; const n = parseFloat(s); return isFinite(n) ? n/100 : d/100; };

  const fmt$ = n => isFinite(n) ? '$'+n.toLocaleString(undefined,{maximumFractionDigits:0}) : '—';

  const fmtp = n => isFinite(n) ? (n*100).toLocaleString(undefined,{maximumFractionDigits:2})+'%' : '—';

  const commas = s => { if(s==null) return ''; const neg=s.startsWith('-'); s=s.replace(/[^\\d.]/g,''); const p=s.split('.'); p[0]=p[0].replace(/^0+(?=\\d)/,'').replace(/\\B(?=(\\d{3})+(?!\\d))/g, ','); return (neg?'-':'') + (p.length>1 ? p[0]+'.'+p[1].slice(0,2) : p[0]); };


  function attachFormatters(){

    document.querySelectorAll('input[data-currency], input[data-percent], input[data-integer]').forEach(inp=>{

      const isInt = inp.hasAttribute('data-integer');

      inp.addEventListener('input', e=>{

        const v = e.target.value; raw.set(inp.id, v);

        const stripped = onlyDigits(v);

        e.target.value = isInt ? commas(stripped.split('.')[0]) : commas(stripped);

        compute();

      });

      inp.addEventListener('blur', compute);

    });

  }


  function addMonths(date, months){

    const d=new Date(date.getTime()), day=d.getDate(); d.setMonth(d.getMonth()+months); if(d.getDate()<day) d.setDate(0); return d;

  }

  const fmtDate = d => `${String(d.getMonth()+1).padStart(2,'0')}/${String(d.getDate()).padStart(2,'0')}/${d.getFullYear()}`;


  function compute(){

    // Inputs

    const asking = parseCurrency('askingPrice');

    const acq    = parseCurrency('acqPrice');

    const newSqf = parseCurrency('newSqft');

    const cpsf   = parseCurrency('costPerSqft');

    const cont   = parsePercent('contPct',5);

    const arch   = parseCurrency('archFee');

    const perm   = parseCurrency('permits');

    const legal  = parseCurrency('legal');


    const taxA = parseCurrency('taxAnnual');

    const insA = parseCurrency('insAnnual');

    const miscA= parseCurrency('miscAnnual');


    const override = $('overrideHold').checked;

    const holdMoAuto = (taxA+insA+miscA)/12;

    if(!override){ $('holdingPerMo').value = commas(String(Math.round(holdMoAuto))); }

    $('holdingPerMo').disabled = !override;

    const holdMo = override ? parseCurrency('holdingPerMo') : holdMoAuto;


    const mPerm = parseCurrency('mPermits');

    const mConst= parseCurrency('mConst');

    const mMkt  = parseCurrency('mMkt');

    const months= Math.max(0, mPerm+mConst+mMkt);

    $('mTotal').value = String(months);


    const closeVal = $('closingDate').value;

    $('exitDateAuto').value = closeVal ? fmtDate(addMonths(new Date(closeVal), months)) : '';


    const cash = $('cashDeal').checked;


    const acqRate = cash ? 0 : parsePercent('acqRate', 0);

    const conRate = cash ? 0 : ($('conRate').value.trim()? parsePercent('conRate',0): acqRate);


    const bankFeePct  = cash ? 0 : parsePercent('bankFeePct',1);

    const brokerFeePct= cash ? 0 : parsePercent('loanFeePct',1);

    const acqClosePct = parsePercent('acqClosePct',2);


    const ltv = cash ? 0 : parsePercent('ltv',75);

    const ltc = cash ? 0 : parsePercent('ltc',80);

    const drawMode = cash ? 'simple' : ($('drawMode').value || 'simple');


    const exitPrice = parseCurrency('exitPrice');

    const saleBrk = parsePercent('saleBrokerPct',5);

    const saleClose = parsePercent('saleClosePct',2);

    const salePct = saleBrk + saleClose;

    const noiY = parseCurrency('noiy');


    // Derived costs

    const hard = newSqf * cpsf;

    const contingency = hard * cont;

    const soft = arch + perm + legal;

    const holding = holdMo * months;

    const acqClosing$ = acq * acqClosePct;


    // Weighted draw months

    const monthsPerm=mPerm, monthsConst=mConst, monthsMkt=mMkt;

    const avgFactor = (drawMode==='simple') ? (monthsPerm*1 + monthsConst*0.5 + monthsMkt*1) : (monthsPerm+monthsConst+monthsMkt);

    const rate = conRate || acqRate;


    // Financing factor k (bank + broker + interest)

    const k = bankFeePct + brokerFeePct + rate*(avgFactor/12);


    const baseCosts = acq + acqClosing$ + hard + contingency + soft + holding;


    const cappedLoan = m => { const d=1 - m*k; return d>0 ? (m*baseCosts)/d : 0; };

    const loanLTV = cappedLoan(ltv);

    const loanLTC = cappedLoan(ltc);

    const loanAmt = cash ? 0 : Math.min(loanLTV, loanLTC);


    const intReserve = cash ? 0 : loanAmt * rate * (avgFactor/12);

    const bankFee$   = cash ? 0 : loanAmt * bankFeePct;

    const brokerFee$ = cash ? 0 : loanAmt * brokerFeePct;


    const saleCosts = exitPrice * salePct;

    const exitNet   = exitPrice - saleCosts;


    const projectCost = baseCosts + intReserve + bankFee$ + brokerFee$;

    const totalCapNeeded = Math.max(0, projectCost - loanAmt);


    // Capital stack ($ complement)

    let sDol = parseCurrency('sponCap');

    let lDol = parseCurrency('lpCap');

    // If user just typed in sponsor, auto-fill LP; vice versa

    const active = document.activeElement ? document.activeElement.id : '';

    if(active === 'sponCap'){

      lDol = Math.max(0, totalCapNeeded - sDol);

      $('lpCap').value = commas(String(Math.round(lDol)));

    } else if(active === 'lpCap'){

      sDol = Math.max(0, totalCapNeeded - lDol);

      $('sponCap').value = commas(String(Math.round(sDol)));

    } else {

      // If LP blank, default to remainder

      if(!(raw.get('lpCap')) && totalCapNeeded > 0){

        lDol = Math.max(0, totalCapNeeded - sDol);

        $('lpCap').value = commas(String(Math.round(lDol)));

      }

    }


    // Percent complement (independent from $)

    const sPct = parsePercent('sponPct') || 0.50;

    const lPct = parsePercent('lpPct')   || (1 - sPct);

    if(document.activeElement && document.activeElement.id === 'sponPct'){

      $('lpPct').value = ( (1 - sPct)*100 ).toFixed(2);

    } else if(document.activeElement && document.activeElement.id === 'lpPct'){

      $('sponPct').value = ( (1 - lPct)*100 ).toFixed(2);

    }


    // Returns

    const equityNeeded = totalCapNeeded;

    const profit = exitNet - projectCost;

    const unlevEquity = baseCosts;

    const uCoC = unlevEquity > 0 ? ((exitNet) - unlevEquity) / unlevEquity : NaN;

    const lCoC = equityNeeded > 0 ? (profit / equityNeeded) : NaN;

    const equityReturn = exitNet - loanAmt;

    const em = (equityNeeded > 0) ? (equityReturn / equityNeeded) : NaN;

    const irr = (equityNeeded > 0 && months > 0 && equityReturn > 0)

      ? (Math.pow(equityReturn / equityNeeded, 12 / months) - 1) : (equityNeeded > 0 && months > 0 && equityReturn === 0 ? -1 : NaN);


    // LP Pref LP CoC

    const lpPref = parsePercent('lpPref',0);

    const lpPrefAccrual = lDol * lpPref * (months/12);

    const lpResidual = Math.max(0, profit - lpPrefAccrual);

    const lpDistribution = Math.min(profit, lpPrefAccrual) + lpResidual * lPct;

    const lpCoC = lDol > 0 ? (lpDistribution / lDol) : NaN;


    const breakevenSale = (1 - salePct) > 0 ? (projectCost / (1 - salePct)) : NaN;

    const moc = projectCost > 0 ? (profit / projectCost) : NaN;

    const yoc = (projectCost > 0 && noiY > 0) ? (noiY / projectCost) : NaN;

    const discount = (asking > 0 && acq > 0) ? ((asking - acq) / asking) : NaN;


    // UI writes

    $('mTotal').value = String(months);

    $('saleCost').value = fmt$(saleCosts);

    $('totalCapNeeded').value = fmt$(totalCapNeeded);

    $('bankFee$').textContent = fmt$(bankFee$);

    $('loanFee$').textContent = fmt$(brokerFee$);

    $('acqClose$').textContent= fmt$(acqClosing$);


    $('discount').textContent = fmtp(discount);

    $('loanAmt').textContent = fmt$(loanAmt);

    $('intRes').textContent = fmt$(intReserve);

    $('hardCosts').textContent = fmt$(hard + contingency);

    $('softCosts').textContent = fmt$(soft);

    $('projCost').textContent = fmt$(projectCost);

    $('profit').textContent = fmt$(profit);

    $('timeHeld').textContent = months + ' mo';

    $('uCoC').textContent = fmtp(uCoC);

    $('lCoC').textContent = fmtp(lCoC);

    $('irr').textContent = isFinite(irr) ? ((irr*100).toFixed(2)+'%') : '—';

    $('em').textContent = isFinite(em) ? em.toFixed(2)+'×' : '—';

    $('lpCoC').textContent = fmtp(lpCoC);

    $('breakeven').textContent = fmt$(breakevenSale);

    $('moc').textContent = fmtp(moc);

    $('yoc').textContent = isFinite(yoc) ? fmtp(yoc) : '—';

  }


  function todayStr(){ const d=new Date(),p=n=>String(n).padStart(2,'0'); return `${d.getFullYear()}.${p(d.getMonth()+1)}.${p(d.getDate())}`; }

  const safeAddr = ()=> ( $('address').value || 'Address').replace(/\s+/g,' ').trim();

  const fileBase = ()=> `${todayStr()} ${safeAddr()} Proforma`;


  function initIO(){

    // Save / Load JSON

    $('btnSave').addEventListener('click', ()=>{

      const ids=[...document.querySelectorAll('input,select')].map(x=>x.id).filter(Boolean);

      const data={}; ids.forEach(id=>data[id]=$(id).value);

      const blob = new Blob([JSON.stringify(data,null,2)],{type:'application/json'});

      const a=document.createElement('a'); a.href=URL.createObjectURL(blob); a.download=fileBase()+'.json'; a.click();

    });

    $('btnLoad').addEventListener('click', ()=>{

      const inp=document.createElement('input'); inp.type='file'; inp.accept='.json,application/json';

      inp.onchange=e=>{ const f=e.target.files[0]; if(!f) return; const r=new FileReader();

        r.onload=()=>{ try{ const data=JSON.parse(r.result); Object.keys(data).forEach(id=>{ if($(id)) $(id).value=data[id]; }); compute(); } catch{ alert('Invalid file'); } };

        r.readAsText(f);

      };

      inp.click();

    });


    // Upload logo (embed as data URL so it prints in PDF)

    $('btnLogo').addEventListener('click', ()=> $('logoFile').click());

    $('logoFile').addEventListener('change', e=>{

      const f=e.target.files[0]; if(!f) return;

      const reader=new FileReader();

      reader.onload=()=>{ // replace the SVG with an <img>

        const brand = document.querySelector('.brand');

        const old = brand.querySelector('svg');

        if(old){ old.remove(); }

        const img=document.createElement('img'); img.src=reader.result; img.alt='PCG Logo';

        brand.insertBefore(img, brand.children[0]);

      };

      reader.readAsDataURL(f);

    });


    // PDF

    $('btnPDF').addEventListener('click', ()=>{

      document.title = fileBase();

      window.print();

    });

  }


  window.addEventListener('DOMContentLoaded', ()=>{

    attachFormatters();

    ['overrideHold','cashDeal','drawMode'].forEach(id=> $(id).addEventListener('change', compute));

    document.querySelectorAll('input').forEach(el=> el.addEventListener('blur', compute));

    compute();

    initIO();

  });

</script>

</body>

</html>