// ======== reports.js ========
const ReportGen = {
  buildRunText(runs, proj) {
    const dm=parseFloat(proj.diameter)||0, pl=parseFloat(proj.length)||0;
    let txt = `Pipeline: ${dm}" x ${Number(pl).toLocaleString()}ft | Client: ${proj.client||"—"} | Job #: ${proj.jobNumber||"—"} | Location: ${proj.location||"—"}\n`;
    txt += `${"─".repeat(60)}\n`;
    runs.forEach(r => {
      const res=Calc.runResults(r,proj);
      const dir = r.direction && r.direction.startsWith("Launch") ? "Launch→Receive (L→R)" : "Receive→Launch (R→L)";
      txt += `\nRUN #${r.runNumber}`;
      if(r.shuttlePasses&&r.shuttlePasses.length>0) txt += ` (Shuttle - ${r.shuttlePasses.length} passes)`;
      txt += `\n`;
      txt += `  Direction: ${dir}\n`;
      txt += `  Pigs: ${r.frontPig}${r.rearPig!=="None"?" / "+r.rearPig:""}\n`;
      txt += `  Chemical: ${r.chemType==="Other"?(r.chemManualType||"Other"):r.chemType} ${r.chemPercent} | Volume: ${r.chemVolume} gal\n`;
      txt += `  Launch: ${Fmt.time(r.launchTime)} | Receive: ${Fmt.time(r.receiveTime)}\n`;
      if(r.shuttlePasses&&r.shuttlePasses.length>0) {
        r.shuttlePasses.forEach((p,pi)=>{
          const pdir = p.direction && p.direction.startsWith("Launch") ? "L→R" : "R→L";
          txt += `  Pass ${pi+1}: ${pdir} | Time: ${Fmt.duration(p.duration)} | Contact: ${p.contactTime}\n`;
        });
      } else {
        txt += `  Run Time: ${res.runTime} | Speed: ${res.speedFtPerSec} ft/s | Contact: ${res.contactTime}\n`;
        txt += `  Solids: ${r.totalSolids} | Acid: ${r.percentAcid} | Color: ${r.solidColor}\n`;
        txt += `  Vol Out: ${r.estVolumeOut} gal | Tank: ${r.tank}\n`;
      }
      if(r.notes) txt += `  Notes: ${r.notes}\n`;
    });
    return txt;
  },

  buildCoatingText(coatingDays, proj) {
    if(!coatingDays||coatingDays.length===0) return "";
    let txt = `\n${"═".repeat(60)}\nCOATING DATA\n${"═".repeat(60)}\n`;
    const runCalc=(run)=>{
      const lbs_loaded=run.totalLbsLoaded||0, lbs_unloaded=run.totalLbsUnloaded||0, lbs_applied=lbs_loaded-lbs_unloaded;
      const mils=Calc.coatingMils(proj,lbs_applied);
      return{lbs_loaded,lbs_unloaded,lbs_applied,mils};
    };
    coatingDays.forEach(d=>{
      txt += `\n${d.label} — ${Fmt.date(d.date)}\n`;
      (d.runs||[]).forEach(r=>{
        const c=runCalc(r);
        txt += `  Run #${r.runNumber}: Loaded: ${c.lbs_loaded.toLocaleString()} lbs | Unloaded: ${c.lbs_unloaded.toLocaleString()} lbs | Applied: ${c.lbs_applied.toLocaleString()} lbs`;
        if(c.mils) txt += ` | Mils: ${c.mils.mils}`;
        txt += `\n`;
      });
    });
    let tl=0,tu=0;
    coatingDays.forEach(d=>(d.runs||[]).forEach(r=>{tl+=r.totalLbsLoaded||0;tu+=r.totalLbsUnloaded||0}));
    const ta=tl-tu, mils=Calc.coatingMils(proj,ta);
    txt += `\nTOTAL: Loaded: ${tl.toLocaleString()} lbs | Unloaded: ${tu.toLocaleString()} lbs | Applied: ${ta.toLocaleString()} lbs`;
    if(mils) txt += ` | Total Mils: ${mils.mils}`;
    txt += `\n`;
    return txt;
  },

  buildJSAText(jsas) {
    if(!jsas||jsas.length===0) return "";
    let txt = `\n${"═".repeat(60)}\nJSA DETAILS\n${"═".repeat(60)}\n`;
    jsas.forEach((j,i)=>{
      txt += `\nJSA #${i+1}: ${j.tasks&&j.tasks.length>0?j.tasks.map(t=>t.type==="Manual Entry"?t.customLabel||"Manual Entry":t.type).join(", "):"(No tasks)"}\n`;
      txt += `  Date: ${j.date||"—"} | Supervisor: ${j.supervisor||"—"}\n`;
      txt += `  Client: ${j.client||"—"} | Location: ${j.location||"—"}\n`;
      txt += `  Evacuation Routes: ${j.evacuationRoutes||"—"}\n`;
      txt += `  Task Start: ${j.taskStartTime||"—"} | Task End: ${j.taskEndTime||"—"}\n`;
      (j.tasks||[]).forEach((task,ti)=>{
        const label = task.type==="Manual Entry"?(task.customLabel||"Manual Entry"):task.type;
        txt += `  Task ${ti+1}: ${label}\n`;
        (task.hazards||[]).forEach((h,hi)=>{
          txt += `    ${String.fromCharCode(65+hi)}. ${h.name}: ${h.mitigation||"(no mitigation entered)"}\n`;
        });
      });
      const fireItems=Object.entries(j.fire||{}).filter(([,v])=>v).map(([k])=>k);
      if(fireItems.length>0) txt += `  Fire Protection: ${fireItems.join(", ")}\n`;
      const ppeItems=Object.entries(j.ppe||{}).filter(([,v])=>v).map(([k])=>k);
      if(ppeItems.length>0) txt += `  PPE: ${ppeItems.join(", ")}\n`;
      if(j.additionalComments) txt += `  Comments: ${j.additionalComments}\n`;
      txt += `  Crew Sign-In: ${(j.crewSignIn||[]).map(s=>s.name).join(", ")||"None"}\n`;
      txt += `  Crew Sign-Out: ${(j.crewSignOut||[]).map(s=>s.name).join(", ")||"None"}\n`;
      if(j.postJobOtherComments) txt += `  Post-Job Notes: ${j.postJobOtherComments}\n`;
    });
    return txt;
  },

  printRunSheet(runs, proj) {
    const dirL=d=>d&&d.startsWith("Launch")?"L\u2192R":"R\u2192L";
    // Build rows — shuttle runs expand into pass sub-rows, regular runs get one row
    let rows="";
    runs.forEach(r=>{
      if(r.shuttlePasses&&r.shuttlePasses.length>0){
        r.shuttlePasses.forEach((p,pi)=>{
          rows+=`<tr style="border-bottom:1px solid #ddd;background:${pi%2===0?'#fff':'#f9f9f9'}">
            <td style="padding:4px 5px;font-weight:700">${r.runNumber}.${pi+1}</td>
            <td style="padding:4px 4px">${Fmt.date(r.date)}</td>
            <td style="padding:4px 4px">${dirL(p.direction)}</td>
            <td style="padding:4px 4px">${r.frontPig}${r.rearPig!=="None"?"/"+r.rearPig:""}${r.thirdPig&&r.thirdPig!=="None"?"/"+r.thirdPig:""}</td>
            <td style="padding:4px 4px">${r.chemType==="Other"?r.chemManualType:r.chemType}</td>
            <td style="padding:4px 4px">${r.chemPercent}</td>
            <td style="padding:4px 4px">${pi===0?r.chemVolume+"g":"\u21BB"}</td>
            <td style="padding:4px 4px">${Fmt.timeShort(p.launchTime)}</td>
            <td style="padding:4px 4px">${Fmt.timeShort(p.receiveTime)}</td>
            <td style="padding:4px 4px">${Fmt.duration(p.duration)}</td>
            <td style="padding:4px 4px">\u2014</td>
            <td style="padding:4px 4px">${p.contactTime||"\u2014"}</td>
            <td style="padding:4px 4px">${p.totalSolids||"\u2014"}</td>
            <td style="padding:4px 4px">${p.percentAcid||"\u2014"}</td>
            <td style="padding:4px 4px">${p.solidColor||"\u2014"}</td>
            <td style="padding:4px 4px">\u2014</td>
            <td style="padding:4px 4px">${pi===0?r.estVolumeOut+"g":"\u2014"}</td>
            <td style="padding:4px 4px">${pi===0?r.tank||"\u2014":"\u2014"}</td>
            <td style="padding:4px 4px;max-width:80px">${pi===0?r.notes||"":"\u2014"}</td>
          </tr>`;
        });
      } else {
        const res=Calc.runResults(r,proj);
        const layered=r.layeredEnabled?`<br><span style="font-size:7px;color:#666">T:${r.layeredTop||""}${r.layeredTopColor?" "+r.layeredTopColor:""} M:${r.layeredMid||""}${r.layeredMidColor?" "+r.layeredMidColor:""} B:${r.layeredBot||""}${r.layeredBotColor?" "+r.layeredBotColor:""}</span>`:"";
        rows+=`<tr style="border-bottom:1px solid #ddd;background:${r.runNumber%2===0?'#f9f9f9':'#fff'}">
          <td style="padding:4px 5px;font-weight:700;color:#b05000">${r.runNumber}</td>
          <td style="padding:4px 4px">${Fmt.date(r.date)}</td>
          <td style="padding:4px 4px">${dirL(r.direction)}</td>
          <td style="padding:4px 4px">${r.frontPig}${r.rearPig!=="None"?"/"+r.rearPig:""}${r.thirdPig&&r.thirdPig!=="None"?"/"+r.thirdPig:""}</td>
          <td style="padding:4px 4px">${r.chemType==="Other"?r.chemManualType:r.chemType}</td>
          <td style="padding:4px 4px">${r.chemPercent}</td>
          <td style="padding:4px 4px">${r.chemVolume}g</td>
          <td style="padding:4px 4px">${Fmt.timeShort(r.launchTime)}</td>
          <td style="padding:4px 4px">${Fmt.timeShort(r.receiveTime)}</td>
          <td style="padding:4px 4px">${res.runTime}</td>
          <td style="padding:4px 4px">${res.speedFtPerSec} ft/s</td>
          <td style="padding:4px 4px">${res.contactTime}</td>
          <td style="padding:4px 4px">${r.totalSolids}${layered}</td>
          <td style="padding:4px 4px">${r.percentAcid}</td>
          <td style="padding:4px 4px">${r.solidColor||"\u2014"}</td>
          <td style="padding:4px 4px">${r.layeredEnabled?`T:${r.layeredTop||""} ${r.layeredTopColor||""} M:${r.layeredMid||""} ${r.layeredMidColor||""} B:${r.layeredBot||""} ${r.layeredBotColor||""}`:"\u2014"}</td>
          <td style="padding:4px 4px">${r.estVolumeOut}g</td>
          <td style="padding:4px 4px">${r.tank||"\u2014"}</td>
          <td style="padding:4px 4px;max-width:80px">${r.notes||"\u2014"}</td>
        </tr>`;
      }
    });
    const html = `<!DOCTYPE html><html><head><title>Cleaning Run Sheet - ${proj.client||""}</title>
    <style>
      body{font-family:Arial,sans-serif;font-size:9px;margin:16px;color:#222}
      h2{font-size:15px;text-align:center;text-decoration:underline;margin-bottom:4px}
      .header-grid{display:grid;grid-template-columns:1fr 1fr 1fr;gap:3px 20px;margin-bottom:14px;font-size:10px}
      table{width:100%;border-collapse:collapse;font-size:8px}
      th{background:#1a2535;color:#fff;padding:4px 3px;text-align:left;font-weight:700;white-space:nowrap}
      td{padding:3px 3px;vertical-align:top}
      .logo{font-size:13px;font-weight:900;color:#b05000}
      .no-print{display:block}
      @page{margin:0;size:landscape}body{padding:8mm 8mm 8mm 8mm}@media print{@page{margin:0;size:landscape}.no-print{display:none!important}tr{page-break-inside:avoid;break-inside:avoid}}
    </style></head><body>
    <div style="display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:10px">
      <div class="logo">INTERNAL PIPELINE SERVICES</div>
      <div style="text-align:right;font-size:9px;color:#666">2440-B Chambers St. \xB7 Venus, TX 76084 \xB7 (817) 539-9764</div>
    </div>
    <h2>Cleaning Run Sheet</h2>
    <div class="header-grid">
      <div><b>Company:</b> ${proj.client||"\u2014"}</div><div><b>Line Size:</b> ${proj.diameter||"\u2014"}"</div><div><b>Job #:</b> ${proj.jobNumber||"\u2014"}</div>
      <div><b>Location:</b> ${proj.location||"\u2014"}</div><div><b>Length:</b> ${Number(proj.length||0).toLocaleString()}'</div><div><b>Product/Type:</b> ${proj.productType||"\u2014"}</div>
    </div>
    <table><thead><tr>
      <th>#</th><th>Date</th><th>Dir</th><th>Pigs</th><th>Chem</th><th>%</th><th>Vol</th>
      <th>Launch</th><th>Receive</th><th>Duration</th><th>Speed</th><th>Contact</th>
      <th>Solids</th><th>Acid%</th><th>Color</th><th>Layered</th><th>Vol Out</th><th>Tank</th><th>Notes</th>
    </tr></thead><tbody>${rows}</tbody></table>
    <div class="no-print" style="margin-top:12px;text-align:right"><button onclick="window.close()" style="background:#eee;border:none;padding:8px 18px;border-radius:6px;font-size:12px;cursor:pointer">\u2715 Close</button></div>
    <script>window.onload=()=>window.print();<\/script></body></html>`;
    const w=window.open("","_blank"); w.document.write(html); w.document.close();
  },

  buildInspectionHTML(inspections) {
    if (!inspections||inspections.length===0) return "";
    const ORIENTATIONS=["12 o'clock","3 o'clock","6 o'clock","9 o'clock"];
    const avgOf=vals=>{const ns=vals.map(v=>parseFloat(v)).filter(v=>!isNaN(v));return ns.length>0?(ns.reduce((a,b)=>a+b,0)/ns.length):null;};
    const fmtA=v=>v!=null?v.toFixed(2):"—";
    const calcLocAvg=loc=>{const avgs=ORIENTATIONS.map(o=>avgOf(loc.readings[o]||[])).filter(v=>v!=null);return avgs.length>0?avgs.reduce((a,b)=>a+b,0)/avgs.length:null;};
    const overall=()=>{const avgs=inspections.map(l=>calcLocAvg(l)).filter(v=>v!=null);return avgs.length>0?avgs.reduce((a,b)=>a+b,0)/avgs.length:null;};
    let html=`<div style="page-break-before:always;margin-top:24px">
      <h3 style="text-align:center;font-size:14px;font-weight:700;margin-bottom:4px">Dry Film Thickness Inspection</h3>`;
    inspections.forEach(loc=>{
      html+=`<div style="margin-bottom:20px"><h4 style="font-size:12px;margin-bottom:6px">Inspection Location: ${loc.name} &nbsp; <span style="font-weight:400;font-size:11px">(${loc.date})</span></h4>
      <table style="width:60%;border-collapse:collapse;font-size:11px;margin-bottom:4px">
        <thead><tr style="background:#f0f0f0"><th style="padding:5px 8px;text-align:left;border:1px solid #ccc">Orientation</th><th style="padding:5px 8px;text-align:center;border:1px solid #ccc">R1</th><th style="padding:5px 8px;text-align:center;border:1px solid #ccc">R2</th><th style="padding:5px 8px;text-align:center;border:1px solid #ccc">R3</th><th style="padding:5px 8px;text-align:right;border:1px solid #ccc">Avg</th></tr></thead>
        <tbody>`;
      ORIENTATIONS.forEach(ori=>{const rv=loc.readings[ori]||["","",""],a=avgOf(rv);html+=`<tr><td style="padding:5px 8px;border:1px solid #ddd">${ori}</td>${rv.map(v=>`<td style="padding:5px 8px;text-align:center;border:1px solid #ddd">${v||"—"}</td>`).join("")}<td style="padding:5px 8px;text-align:right;font-weight:700;border:1px solid #ddd">${fmtA(a)}</td></tr>`;});
      html+=`</tbody><tfoot><tr style="background:#f5f5f5"><td colspan="4" style="padding:6px 8px;font-weight:700;border:1px solid #ccc">Average DFT</td><td style="padding:6px 8px;text-align:right;font-weight:900;font-size:13px;border:2px solid #888">${fmtA(calcLocAvg(loc))}</td></tr></tfoot></table></div>`;
    });
    if(inspections.length>1) html+=`<div style="display:inline-block;border:2px solid #333;padding:8px 16px;font-weight:900;font-size:14px;margin-top:8px">Total Average DFT: ${fmtA(overall())}</div>`;
    html+=`</div>`;
    return html;
  },

  // Pre-fetch Firebase Storage photos as base64 so they embed cleanly in printed HTML.
  // Returns a map of { [photoId]: "data:image/jpeg;base64,..." }
  async fetchPhotosAsBase64(photos) {
    const result = {};
    await Promise.all((photos||[]).map(async photo => {
      const url = photo.storageUrl || photo.dataUrl || null;
      if (!url) return;
      // Already a data URL — no fetch needed
      if (url.startsWith("data:")) { result[photo.id] = url; return; }
      try {
        const resp = await fetch(url);
        if (!resp.ok) return;
        const blob = await resp.blob();
        await new Promise(resolve => {
          const reader = new FileReader();
          reader.onload = e => { result[photo.id] = e.target.result; resolve(); };
          reader.onerror = () => resolve();
          reader.readAsDataURL(blob);
        });
      } catch(e) { /* skip failed photos */ }
    }));
    return result;
  },

  printHTML(title, bodyHTML) {
    const html=`<!DOCTYPE html><html><head><title>${title}</title>
    <style>body{font-family:Arial,sans-serif;font-size:11px;margin:20px;color:#222;line-height:1.5}
    h1{font-size:18px;margin-bottom:4px}h2{font-size:15px;border-bottom:2px solid #b05000;padding-bottom:4px;margin:16px 0 10px}
    h3{font-size:13px;margin:10px 0 6px;color:#b05000}table{width:100%;border-collapse:collapse;margin-bottom:12px}
    th{background:#1a2535;color:#fff;padding:5px 6px;font-size:10px;text-align:left}
    td{padding:4px 6px;border-bottom:1px solid #eee;font-size:10px}
    .logo{font-size:14px;font-weight:900;color:#b05000;margin-bottom:2px}
    .meta{font-size:11px;color:#555;margin-bottom:16px}
    .section{margin-bottom:18px;padding:12px;border:1px solid #ddd;border-radius:4px}
    .kv{display:inline-block;margin-right:20px;margin-bottom:4px}
    .kv b{color:#555;font-weight:600}
    @page{margin:0}body{padding:12mm 14mm}@media print{@page{margin:0}.no-print{display:none!important}}</style></head>
    <body>${bodyHTML}<script>window.onload=()=>window.print();</script></body></html>`;
    const w=window.open("","_blank"); w.document.write(html); w.document.close();
  },

  buildDailyHTML(proj, dayRuns, dayNote, dayDate, dayCoating, dayJSAs, inspections, photos, allJsas, photoBase64Map) {
    const dirLabel=d=>d&&d.startsWith("Launch")?"L→R":"R→L";
    const fmtHrs=h=>{if(!h||h<=0)return"—";const tm=Math.round(h*60),hr=Math.floor(tm/60),mn=tm%60;return hr>0?`${hr}h ${mn}m`:`${mn}m`;};
    const msToHours=ms=>ms/3600000;
    const getTs=s=>(s.time&&typeof s.time==="number")?s.time:null;

    // ── Header ──────────────────────────────────────────────────────────────
    let body=`<div class="logo">INTERNAL PIPELINE SERVICES</div>
    <div class="meta">2440-B Chambers St. · Venus, TX 76084 · (817) 539-9764</div>
    <h1 style="margin:4px 0 2px">Daily Report — ${dayDate}</h1>
    <div class="meta" style="margin-bottom:8px"><b>Client:</b> ${proj.client||"—"} &nbsp;|&nbsp; <b>Job #:</b> ${proj.jobNumber||"—"} &nbsp;|&nbsp; <b>Location:</b> ${proj.location||"—"} &nbsp;|&nbsp; ${proj.diameter||"—"}" × ${Number(proj.length||0).toLocaleString()}ft</div>`;

    // ── Run Log (compact — one row per run, abbreviated) ────────────────────
    if(dayRuns.length>0){
      body+=`<h2 style="margin:8px 0 4px">Run Log</h2><table style="font-size:9px"><thead><tr><th>#</th><th>Dir</th><th>Pigs</th><th>Chem</th><th>%</th><th>Vol</th><th>Launch</th><th>Rcv</th><th>Dur</th><th>Vol Out</th><th>Tank</th><th>Solids</th><th>Acid%</th><th>Color</th><th>Notes</th></tr></thead><tbody>`;
      dayRuns.forEach(r=>{
        const chem=r.chemType==="Other"?r.chemManualType:r.chemType;
        const pigs=[r.frontPig,r.rearPig!=="None"?r.rearPig:null,r.thirdPig&&r.thirdPig!=="None"?r.thirdPig:null].filter(Boolean).join("/");
        if(r.shuttlePasses&&r.shuttlePasses.length>0){
          // Shuttle: one summary row then pass sub-rows
          const totalDur=r.shuttlePasses.reduce((s,p)=>s+(p.duration||0),0);
          body+=`<tr style="background:#fff8f0"><td><b>${r.runNumber}</b></td><td colspan="2" style="font-style:italic;color:#b05000">🔄 Shuttle (${r.shuttlePasses.length} passes) · ${pigs}</td><td>${chem}</td><td>${r.chemPercent}</td><td>${r.chemVolume}g</td><td>${Fmt.timeShort(r.shuttlePasses[0]?.launchTime)}</td><td>${Fmt.timeShort(r.shuttlePasses[r.shuttlePasses.length-1]?.receiveTime)}</td><td>${Fmt.duration(totalDur)}</td><td>${r.estVolumeOut}g</td><td>${r.tank}</td><td>—</td><td>—</td><td>—</td><td>${r.notes||"—"}</td></tr>`;
          r.shuttlePasses.forEach((p,pi)=>{
            body+=`<tr style="background:#fffaf5"><td style="padding-left:10px;color:#b05000;font-size:8px">${r.runNumber}.${pi+1}</td><td style="font-size:8px;color:#b05000">${dirLabel(p.direction)}</td><td></td><td></td><td></td><td></td><td style="font-size:8px">${Fmt.timeShort(p.launchTime)}</td><td style="font-size:8px">${Fmt.timeShort(p.receiveTime)}</td><td style="font-size:8px">${Fmt.duration(p.duration)}</td><td></td><td></td><td style="font-size:8px">${p.totalSolids||"—"}</td><td style="font-size:8px">${p.percentAcid||"—"}</td><td style="font-size:8px">${p.solidColor||"—"}</td><td style="font-size:8px">Contact: ${p.contactTime}</td></tr>`;
          });
        } else {
          const res=Calc.runResults(r,proj);
          body+=`<tr><td><b>${r.runNumber}</b></td><td>${dirLabel(r.direction)}</td><td>${pigs}</td><td>${chem}</td><td>${r.chemPercent}</td><td>${r.chemVolume}g</td><td>${Fmt.timeShort(r.launchTime)}</td><td>${Fmt.timeShort(r.receiveTime)}</td><td>${Fmt.duration(r.duration)}</td><td>${r.estVolumeOut}g</td><td>${r.tank}</td><td>${r.totalSolids}</td><td>${r.percentAcid}</td><td>${r.solidColor}</td><td>${r.notes||"—"}</td></tr>`;
        }
      });
      body+=`</tbody></table>`;
    } else body+=`<p style="font-size:10px;font-style:italic;margin:4px 0 8px">No runs recorded for this day.</p>`;

    // ── Coating ─────────────────────────────────────────────────────────────
    if(dayCoating&&dayCoating.length>0){
      body+=`<h2 style="margin:8px 0 4px">Coating</h2>`;
      dayCoating.forEach(cd=>{
        body+=`<h3 style="margin:4px 0 2px">${cd.label}</h3><table style="font-size:9px"><thead><tr><th>Run #</th><th>Lbs In</th><th>Lbs Out</th><th>Lbs Applied</th><th>Mils</th></tr></thead><tbody>`;
        (cd.runs||[]).forEach(cr=>{const ta=(cr.totalLbsLoaded||0)-(cr.totalLbsUnloaded||0),mils=Calc.coatingMils(proj,ta);body+=`<tr><td>${cr.runNumber}</td><td>${(cr.totalLbsLoaded||0).toLocaleString()}</td><td>${(cr.totalLbsUnloaded||0).toLocaleString()}</td><td>${ta.toLocaleString()}</td><td>${mils?mils.mils:"—"}</td></tr>`;});
        body+=`</tbody></table>`;
      });
    }

    // ── JSAs (condensed) ────────────────────────────────────────────────────
    if(dayJSAs&&dayJSAs.length>0){
      body+=`<h2 style="margin:8px 0 4px">JSAs</h2>`;
      dayJSAs.forEach((j,i)=>{
        const taskLabel=j.tasks&&j.tasks.length>0?j.tasks.map(t=>t.type==="Manual Entry"?t.customLabel||"Manual Entry":t.type).join(", "):"(No tasks)";
        const tasksWithHazards=(j.tasks||[]).map((t,ti)=>{const lbl=t.type==="Manual Entry"?t.customLabel||"Manual Entry":t.type;const hz=(t.hazards||[]).map(h=>h.name).join(", ");return lbl+(hz?` [${hz}]`:"");}).join(" | ");
        const crewIn=(j.crewSignIn||[]).map(s=>s.name).join(", ")||"None";
        const crewOut=(j.crewSignOut||[]).map(s=>s.name).join(", ")||"None";
        body+=`<div class="section" style="padding:7px 10px;margin-bottom:8px">
          <div style="font-weight:700;font-size:11px;margin-bottom:3px">JSA #${i+1}: ${taskLabel}</div>
          <div style="font-size:9px;color:#555;line-height:1.6">
            <span class="kv"><b>Supervisor:</b> ${j.supervisor||"—"}</span><span class="kv"><b>Location:</b> ${j.location||"—"}</span><span class="kv"><b>Start:</b> ${j.taskStartTime||"—"}</span><span class="kv"><b>End:</b> ${j.taskEndTime||"—"}</span>
          </div>
          ${tasksWithHazards?`<div style="font-size:9px;color:#333;margin-top:2px"><b>Tasks/Hazards:</b> ${tasksWithHazards}</div>`:""}
          <div style="font-size:9px;color:#333;margin-top:2px"><b>Crew In:</b> ${crewIn} &nbsp;|&nbsp; <b>Crew Out:</b> ${crewOut}</div>
          ${j.additionalComments?`<div style="font-size:9px;color:#555;margin-top:2px"><b>Notes:</b> ${j.additionalComments}</div>`:""}
        </div>`;
      });
    }

    // ── Man Hours ────────────────────────────────────────────────────────────
    const includedJSAs=(dayJSAs||[]).filter(j=>j.includeHoursInReport);
    if(includedJSAs.length>0){
      const personMs={};
      includedJSAs.forEach(jsa=>{
        const inMap={},outMap={};
        (jsa.crewSignIn||[]).forEach(s=>{const ts=getTs(s);if(s.name&&ts)inMap[s.name]=ts;});
        (jsa.crewSignOut||[]).forEach(s=>{const ts=getTs(s);if(s.name&&ts)outMap[s.name]=ts;});
        const names=[...new Set([...Object.keys(inMap),...Object.keys(outMap)])];
        names.forEach(name=>{
          const inTs=inMap[name]||null,outTs=outMap[name]||null;
          const ms=(inTs&&outTs&&outTs>inTs)?outTs-inTs:null;
          if(ms){if(!personMs[name])personMs[name]=0;personMs[name]+=ms;}
        });
      });
      if(Object.keys(personMs).length>0){
        const dayTotalMs=Object.values(personMs).reduce((s,ms)=>s+ms,0);
        const crewCount=Object.keys(personMs).length;
        body+=`<h2 style="margin:8px 0 4px">Man Hours</h2><div class="section" style="padding:7px 10px;margin-bottom:8px">
          <table style="font-size:9px;width:auto;min-width:260px"><thead><tr><th style="text-align:left">Name</th><th>Time In</th><th>Time Out</th><th>Hours</th></tr></thead><tbody>`;
        Object.entries(personMs).sort((a,b)=>a[0].localeCompare(b[0])).forEach(([name,ms])=>{
          // find in/out times from first included JSA that has this person
          let inTs=null,outTs=null;
          includedJSAs.forEach(jsa=>{
            if(!inTs)(jsa.crewSignIn||[]).forEach(s=>{if(s.name===name&&getTs(s))inTs=getTs(s);});
            if(!outTs)(jsa.crewSignOut||[]).forEach(s=>{if(s.name===name&&getTs(s))outTs=getTs(s);});
          });
          const h=msToHours(ms);
          body+=`<tr><td style="font-weight:600;text-align:left">${name}</td><td style="text-align:center">${inTs?Fmt.timeShort(inTs):"—"}</td><td style="text-align:center">${outTs?Fmt.timeShort(outTs):"—"}</td><td style="font-weight:700;text-align:right">${fmtHrs(h)} (${h.toFixed(2)})</td></tr>`;
        });
        body+=`</tbody><tfoot><tr style="border-top:2px solid #b05000"><td colspan="3" style="font-weight:700;text-align:left;padding-top:4px">Today — ${crewCount} crew member${crewCount!==1?"s":""}</td><td style="font-weight:900;text-align:right;color:#b05000;padding-top:4px">${fmtHrs(msToHours(dayTotalMs))} (${msToHours(dayTotalMs).toFixed(2)} hrs)</td></tr>`;
        // Project total across ALL included JSAs in the whole project
        if(allJsas&&allJsas.length>0){
          const projPersonMs={};
          allJsas.forEach(jsa=>{
            const inMap={},outMap={};
            (jsa.crewSignIn||[]).forEach(s=>{const ts=getTs(s);if(s.name&&ts)inMap[s.name]=ts;});
            (jsa.crewSignOut||[]).forEach(s=>{const ts=getTs(s);if(s.name&&ts)outMap[s.name]=ts;});
            const names=[...new Set([...Object.keys(inMap),...Object.keys(outMap)])];
            names.forEach(name=>{const inTs=inMap[name]||null,outTs=outMap[name]||null;const ms=(inTs&&outTs&&outTs>inTs)?outTs-inTs:null;if(ms){if(!projPersonMs[name])projPersonMs[name]=0;projPersonMs[name]+=ms;}});
          });
          const projTotalMs=Object.values(projPersonMs).reduce((s,ms)=>s+ms,0);
          if(projTotalMs>0) body+=`<tr><td colspan="3" style="font-weight:700;text-align:left;padding-top:3px;color:#555">Project Total (all days)</td><td style="font-weight:900;text-align:right;color:#555;padding-top:3px">${fmtHrs(msToHours(projTotalMs))} (${msToHours(projTotalMs).toFixed(2)} hrs)</td></tr>`;
        }
        body+=`</tfoot></table></div>`;
      }
    }

    // ── Field Notes ──────────────────────────────────────────────────────────
    if(dayNote?.text) body+=`<h2 style="margin:8px 0 4px">Field Notes</h2><p style="white-space:pre-wrap;line-height:1.6;font-size:10px;margin:0 0 8px">${dayNote.text}</p>`;

    // ── Photos ───────────────────────────────────────────────────────────────
    const dailyPhotos=(photos||[]).filter(p=>p.addToDaily);
    if(dailyPhotos.length>0){
      body+=`<h2 style="margin:8px 0 4px">Photos</h2><div class="photo-grid">`;
      dailyPhotos.forEach(p=>{
        const ts=new Date(p.timestamp).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})+" "+new Date(p.timestamp).toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit",hour12:true});
        const imgSrc=(photoBase64Map&&photoBase64Map[p.id])||p.storageUrl||p.dataUrl||"";
        if(imgSrc)body+=`<div class="photo-card"><img src="${imgSrc}" /><div class="photo-caption"><div style="font-size:8px;color:#888;font-weight:700;margin-bottom:1px">${ts}</div>${p.description?`<div style="font-size:9px;color:#333">${p.description}</div>`:""}</div></div>`;
      });
      body+=`</div>`;
    }
    return body;
  },

  buildFinalHTML(proj, runs, dailyNotes, coatingDays, inspections, review, photos, photoBase64Map) {
    const t=Calc.projectTotals(runs,proj);
    const runDates=runs.map(r=>r.date).filter(Boolean);
    const sd=proj.startDate||(runDates.length>0?Fmt.date(Math.min(...runDates)):"—");
    const ed=proj.endDate||(runDates.length>0?Fmt.date(Math.max(...runDates)):"—");
    const calcSpanDays=(s,e)=>{try{const a=new Date(s),b=new Date(e);if(isNaN(a)||isNaN(b))return null;const d=Math.round((b-a)/86400000)+1;return d>0?d:null;}catch(e){return null;}};
    const spanDays=calcSpanDays(sd,ed);
    const spanStr=spanDays!=null?`${spanDays} day${spanDays!==1?"s":""}`:`${[...new Set(runs.map(r=>Fmt.date(r.date)))].length} day${[...new Set(runs.map(r=>Fmt.date(r.date)))].length!==1?"s":""}`;
    const dirLbl=d=>d&&d.startsWith("Launch")?"L\u2192R":"R\u2192L";
    let body=`<div class="logo">INTERNAL PIPELINE SERVICES</div>
    <div class="meta">2440-B Chambers St. · Venus, TX 76084 · (817) 539-9764</div>
    <h1>${proj.diameter||"—"}" × ${Number(proj.length||0).toLocaleString()}ft IPS Project Report</h1>
    <div class="meta"><b>Client:</b> ${proj.client||"—"} &nbsp;|&nbsp; <b>Job #:</b> ${proj.jobNumber||"—"} &nbsp;|&nbsp; <b>Location:</b> ${proj.location||"—"} &nbsp;|&nbsp; <b>Product:</b> ${proj.productType||"—"} &nbsp;|&nbsp; <b>Dates:</b> ${sd} – ${ed}</div>
    <h2>Executive Summary</h2>
    <p>The project consisted of ${Number(proj.length||0).toLocaleString()} ft of ${proj.diameter||"—"}" pipeline located in ${proj.location||"the field"}. The project took place from ${sd} through ${ed}, spanning ${spanStr}. A total of ${t.totalRuns} pig runs were completed with a cumulative run time of ${t.totalRunTime}. The average pig speed was ${t.avgSpeedFtSec} ft/sec. Total chemical volume loaded was ${t.totalVolLoaded.toLocaleString()} gallons with ${t.totalVolOut.toLocaleString()} gallons recovered.</p>
    <h2>Project Summary</h2>
    <div class="section">
      <span class="kv"><b>Total Runs:</b> ${t.totalRuns}</span><span class="kv"><b>Total Run Time:</b> ${t.totalRunTime}</span><span class="kv"><b>Avg Speed:</b> ${t.avgSpeedFtSec} ft/s</span><br>
      <span class="kv"><b>Vol Loaded:</b> ${t.totalVolLoaded.toLocaleString()} gal</span><span class="kv"><b>Vol Out:</b> ${t.totalVolOut.toLocaleString()} gal</span>
      ${t.chemByType&&Object.keys(t.chemByType).length>0?`<br><b>Chemical Breakdown:</b> ${Object.entries(t.chemByType).map(([k,v])=>`${k}: ${v.toLocaleString()} gal`).join(" | ")}`:""}
    </div>`;
    body+=`<h2>Methodology</h2>
    <div class="section">
      <h3>A. Data Collection — Batch Samples</h3>
      <p>Chemical and water flush batches were retrieved from the receiving side of the pipeline. A Camphor test was conducted to verify the removal of hydrocarbons. A quantitative analysis for determining HCL Acid concentration for each HCL batch was carried out by means of titration method. Water Flush samples were analyzed for percent of solids by means of centrifuge.</p>
      <h3>B. Atmospheric &amp; Desiccant Dryer Data Collection</h3>
      <p>Atmospheric conditions and the desiccant dryer's dew point were analyzed using a Fluke 971 Temperature Humidity Meter.</p>
      <h3>C. Water Testing Method</h3>
      <p>The water used for cleaning batches and water flushes was tested for chloride levels by means of Quantab chloride titration strips in the PPM range of 45 to 480.</p>
      <h3>D. Epoxy Coating &amp; Surface Profile Data Collection</h3>
      <p>The epoxy coating's viscosity was measured using a Viscometer. The coating was weighed using a pallet scale and coating samples were weighed using a lab grade digital scale. The coating's temperature was measured using a lab grade infrared temperature gun. The Dry Film Thickness (DFT) is measured using a Mikrotest magnetic coating thickness / PosiTest DFT gauge.</p>
    </div>`;
    body+=`<h2>Run Sheet</h2>
    <table style="font-size:8px"><thead><tr><th>#</th><th>Date</th><th>Dir</th><th>Pigs</th><th>Chem</th><th>%</th><th>Vol</th><th>Launch</th><th>Receive</th><th>Dur.</th><th>Solids</th><th>Acid%</th><th>Color</th><th>Vol Out</th><th>Notes</th></tr></thead><tbody>`;
    runs.forEach(r=>{
      if(r.shuttlePasses&&r.shuttlePasses.length>0){
        r.shuttlePasses.forEach((p,pi)=>{
          const pigStr=[r.frontPig,r.rearPig!=="None"?r.rearPig:null,r.thirdPig&&r.thirdPig!=="None"?r.thirdPig:null].filter(Boolean).join("/");
          body+=`<tr style="background:${pi%2===0?"#fffbf5":"#fff"}"><td><b>${r.runNumber}.${pi+1}</b></td><td>${Fmt.date(r.date)}</td><td style="font-weight:700;color:${p.direction&&p.direction.startsWith("Launch")?"#1565c0":"#b71c1c"}">${dirLbl(p.direction)}</td><td>${pigStr}</td><td>${r.chemType==="Other"?r.chemManualType:r.chemType}</td><td>${r.chemPercent}</td><td>${pi===0?r.chemVolume+"g":"\u21BB"}</td><td>${Fmt.timeShort(p.launchTime)}</td><td>${Fmt.timeShort(p.receiveTime)}</td><td>${Fmt.duration(p.duration)}</td><td>${p.totalSolids||"\u2014"}</td><td>${p.percentAcid||"\u2014"}</td><td>${p.solidColor||"\u2014"}</td><td>${pi===0?r.estVolumeOut+"g":"\u2014"}</td><td>${pi===0?r.notes||"":""}</td></tr>`;
        });
      } else {
        const res=Calc.runResults(r,proj);
        const pigStr=[r.frontPig,r.rearPig!=="None"?r.rearPig:null,r.thirdPig&&r.thirdPig!=="None"?r.thirdPig:null].filter(Boolean).join("/");
        body+=`<tr><td><b style="color:#b05000">${r.runNumber}</b></td><td>${Fmt.date(r.date)}</td><td style="font-weight:700;color:${r.direction&&r.direction.startsWith("Launch")?"#1565c0":"#b71c1c"}">${dirLbl(r.direction)}</td><td>${pigStr}</td><td>${r.chemType==="Other"?r.chemManualType:r.chemType}</td><td>${r.chemPercent}</td><td>${r.chemVolume}g</td><td>${Fmt.timeShort(r.launchTime)}</td><td>${Fmt.timeShort(r.receiveTime)}</td><td>${res.runTime}</td><td>${r.totalSolids||"\u2014"}</td><td>${r.percentAcid||"\u2014"}</td><td>${r.solidColor||"\u2014"}</td><td>${r.estVolumeOut}g</td><td>${r.notes||""}</td></tr>`;
      }
    });
    body+=`</tbody></table>`;
    if(coatingDays&&coatingDays.length>0){
      body+=`<h2>Coating Run Sheet</h2><table><thead><tr><th>Date</th><th>Run #</th><th>Front</th><th>Rear</th><th>Launch</th><th>Receive</th><th>Dur.</th><th>Lbs In</th><th>Lbs Out</th><th>Lbs Applied</th><th>Sq Ft</th><th>Gals/Mil</th><th>Lbs/Mil</th><th>Mils</th></tr></thead><tbody>`;
      coatingDays.forEach(d=>{(d.runs||[]).forEach(r=>{
        const ta=(r.totalLbsLoaded||0)-(r.totalLbsUnloaded||0),mils=Calc.coatingMils(proj,ta);
        const runDur=(r.launchTime&&r.receiveTime)?Fmt.duration(r.receiveTime-r.launchTime):"—";
        body+=`<tr><td>${Fmt.date(d.date)}</td><td>${r.runNumber}</td><td>${r.frontPig||"—"}</td><td>${r.rearPig||"—"}</td><td>${Fmt.timeShort(r.launchTime)}</td><td>${Fmt.timeShort(r.receiveTime)}</td><td>${runDur}</td><td>${(r.totalLbsLoaded||0).toLocaleString()}</td><td>${(r.totalLbsUnloaded||0).toLocaleString()}</td><td>${ta.toLocaleString()}</td><td>${mils?mils.sqFt+"ft²":"—"}</td><td>${mils?mils.galsPerMil:"—"}</td><td>${mils?mils.lbsPerMil:"—"}</td><td style="font-weight:700">${mils?mils.mils:"—"}</td></tr>`;
      });});
      let tl=0,tu=0; coatingDays.forEach(d=>(d.runs||[]).forEach(r=>{tl+=r.totalLbsLoaded||0;tu+=r.totalLbsUnloaded||0;}));
      const ta=tl-tu,mils=Calc.coatingMils(proj,ta);
      body+=`<tr style="background:#f0f0f0;font-weight:700"><td colspan="9">TOTAL</td><td>${ta.toLocaleString()} lbs</td><td>${mils?mils.sqFt+"ft²":"—"}</td><td>${mils?mils.galsPerMil:"—"}</td><td>${mils?mils.lbsPerMil:"—"}</td><td style="font-size:13px">${mils?mils.mils+" mils":"—"}</td></tr></tbody></table>`;
    }
    if(inspections&&inspections.length>0) body+=this.buildInspectionHTML(inspections);
    const nwt=(dailyNotes||[]).filter(n=>n.text);
    if(nwt.length>0){body+=`<h2>Daily Report Breakdown</h2>`;nwt.sort((a,b)=>new Date(a.date)-new Date(b.date)).forEach(n=>{body+=`<h3>${n.date}</h3><p style="white-space:pre-wrap;line-height:1.7">${n.text}</p>`;});}
    // Photos section for final report
    const finalPhotos = (photos||[]).filter(p=>p.addToFinal);
    if(finalPhotos.length>0){
      body+=`<h2>Project Photos</h2><div class="photo-grid">`;
      finalPhotos.forEach(p=>{
        const ts=new Date(p.timestamp).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})+" "+new Date(p.timestamp).toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit",hour12:true});
        const imgSrc=(photoBase64Map&&photoBase64Map[p.id])||p.storageUrl||p.dataUrl||"";
        if(imgSrc)body+=`<div class="photo-card"><img src="${imgSrc}" /><div class="photo-caption"><div style="font-size:9px;color:#888;font-weight:700;margin-bottom:2px">${ts}</div>${p.description?`<div style="font-size:12px;color:#333">${p.description}</div>`:""}</div></div>`;
      });
      body+=`</div>`;
    }
    if(false&&review&&review.stars){const stars="★".repeat(review.stars)+"☆".repeat(5-review.stars);body+=`<h2>Customer Review</h2><p style="font-size:18px">${stars} (${review.stars}/5)</p><p>${review.text||""}</p>`;}
    return body;
  },

  buildArchiveHTML(proj, runs, dailyNotes, coatingDays, jsas, deliveries, compData, inspections, checklist, photos, photoBase64Map) {
    const dirLbl=d=>d&&d.startsWith("Launch")?"L\u2192R":"R\u2192L";
    const t=Calc.projectTotals(runs,proj);
    const genTs=new Date().toLocaleString("en-US");

    let body=`<div class="logo">INTERNAL PIPELINE SERVICES</div>
    <div class="meta">2440-B Chambers St. · Venus, TX 76084 · (817) 539-9764</div>
    <h1>Complete Project Archive</h1>
    <div class="meta">Generated ${genTs} — this document is the full record of every data type stored for this project.</div>

    <h2>Project Information</h2>
    <div class="section">
      <span class="kv"><b>Project #:</b> ${proj.projectNumber||"—"}</span><span class="kv"><b>Client:</b> ${proj.client||"—"}</span><span class="kv"><b>Job #:</b> ${proj.jobNumber||"—"}</span><br>
      <span class="kv"><b>Location:</b> ${proj.location||"—"}</span><span class="kv"><b>Product/Type:</b> ${proj.productType||"—"}</span><br>
      <span class="kv"><b>Line Size:</b> ${proj.diameter||"—"}" (Actual ID: ${proj.actualID||"—"})</span><span class="kv"><b>Length:</b> ${Number(proj.length||0).toLocaleString()} ft</span><br>
      <span class="kv"><b>Start Date:</b> ${proj.startDate||"—"}</span><span class="kv"><b>End Date:</b> ${proj.endDate||"—"}</span><span class="kv"><b>Status:</b> ${proj.closed?"Closed":"Open"}</span><br>
      <span class="kv"><b>Default Tank:</b> ${proj.defaultTank||"—"}</span><span class="kv"><b>Contact Email:</b> ${proj.email||"—"}</span>
    </div>

    <h2>Summary Totals</h2>
    <div class="section">
      <span class="kv"><b>Total Runs:</b> ${t.totalRuns}</span><span class="kv"><b>Total Run Time:</b> ${t.totalRunTime}</span><span class="kv"><b>Avg Speed:</b> ${t.avgSpeedFtSec} ft/s</span><br>
      <span class="kv"><b>Vol Loaded:</b> ${t.totalVolLoaded.toLocaleString()} gal</span><span class="kv"><b>Vol Out:</b> ${t.totalVolOut.toLocaleString()} gal</span>
      ${t.chemByType&&Object.keys(t.chemByType).length>0?`<br><b>Chemical Breakdown:</b> ${Object.entries(t.chemByType).map(([k,v])=>`${k}: ${v.toLocaleString()} gal`).join(" | ")}`:""}
    </div>`;

    // ── Full Run Sheet — every run, no filtering ────────────────────────────
    body+=`<h2>Full Run Sheet (${runs.length} runs)</h2>`;
    if(runs.length===0){ body+=`<p style="color:#888">No runs recorded.</p>`; }
    else {
      body+=`<table style="font-size:8px"><thead><tr><th>#</th><th>Date</th><th>Dir</th><th>Pigs</th><th>Chem</th><th>%</th><th>Vol</th><th>Launch</th><th>Receive</th><th>Dur.</th><th>Solids</th><th>Acid%</th><th>Color</th><th>Vol Out</th><th>Tank</th><th>Notes</th></tr></thead><tbody>`;
      runs.forEach(r=>{
        if(r.shuttlePasses&&r.shuttlePasses.length>0){
          r.shuttlePasses.forEach((p,pi)=>{
            const pigStr=[r.frontPig,r.rearPig!=="None"?r.rearPig:null,r.thirdPig&&r.thirdPig!=="None"?r.thirdPig:null].filter(Boolean).join("/");
            body+=`<tr style="background:${pi%2===0?"#fffbf5":"#fff"}"><td><b>${r.runNumber}.${pi+1}</b></td><td>${Fmt.date(r.date)}</td><td style="font-weight:700;color:${p.direction&&p.direction.startsWith("Launch")?"#1565c0":"#b71c1c"}">${dirLbl(p.direction)}</td><td>${pigStr}</td><td>${r.chemType==="Other"?r.chemManualType:r.chemType}</td><td>${r.chemPercent}</td><td>${pi===0?r.chemVolume+"g":"\u21BB"}</td><td>${Fmt.timeShort(p.launchTime)}</td><td>${Fmt.timeShort(p.receiveTime)}</td><td>${Fmt.duration(p.duration)}</td><td>${p.totalSolids||"\u2014"}</td><td>${p.percentAcid||"\u2014"}</td><td>${p.solidColor||"\u2014"}</td><td>${pi===0?r.estVolumeOut+"g":"\u2014"}</td><td>${r.tank||"\u2014"}</td><td>${pi===0?r.notes||"":""}</td></tr>`;
          });
        } else {
          const res=Calc.runResults(r,proj);
          const pigStr=[r.frontPig,r.rearPig!=="None"?r.rearPig:null,r.thirdPig&&r.thirdPig!=="None"?r.thirdPig:null].filter(Boolean).join("/");
          body+=`<tr><td><b style="color:#b05000">${r.runNumber}</b></td><td>${Fmt.date(r.date)}</td><td style="font-weight:700;color:${r.direction&&r.direction.startsWith("Launch")?"#1565c0":"#b71c1c"}">${dirLbl(r.direction)}</td><td>${pigStr}</td><td>${r.chemType==="Other"?r.chemManualType:r.chemType}</td><td>${r.chemPercent}</td><td>${r.chemVolume}g</td><td>${Fmt.timeShort(r.launchTime)}</td><td>${Fmt.timeShort(r.receiveTime)}</td><td>${res.runTime}</td><td>${r.totalSolids||"\u2014"}</td><td>${r.percentAcid||"\u2014"}</td><td>${r.solidColor||"\u2014"}</td><td>${r.estVolumeOut}g</td><td>${r.tank||"\u2014"}</td><td>${r.notes||""}</td></tr>`;
        }
      });
      body+=`</tbody></table>`;
    }

    // ── Coating ──────────────────────────────────────────────────────────────
    if(coatingDays&&coatingDays.length>0){
      body+=`<h2>Coating Run Sheet</h2><table><thead><tr><th>Date</th><th>Run #</th><th>Front</th><th>Rear</th><th>Launch</th><th>Receive</th><th>Dur.</th><th>Lbs In</th><th>Lbs Out</th><th>Lbs Applied</th><th>Sq Ft</th><th>Gals/Mil</th><th>Lbs/Mil</th><th>Mils</th></tr></thead><tbody>`;
      coatingDays.forEach(d=>{(d.runs||[]).forEach(r=>{
        const ta=(r.totalLbsLoaded||0)-(r.totalLbsUnloaded||0),mils=Calc.coatingMils(proj,ta);
        const runDur=(r.launchTime&&r.receiveTime)?Fmt.duration(r.receiveTime-r.launchTime):"—";
        body+=`<tr><td>${Fmt.date(d.date)}</td><td>${r.runNumber}</td><td>${r.frontPig||"—"}</td><td>${r.rearPig||"—"}</td><td>${Fmt.timeShort(r.launchTime)}</td><td>${Fmt.timeShort(r.receiveTime)}</td><td>${runDur}</td><td>${(r.totalLbsLoaded||0).toLocaleString()}</td><td>${(r.totalLbsUnloaded||0).toLocaleString()}</td><td>${ta.toLocaleString()}</td><td>${mils?mils.sqFt+"ft²":"—"}</td><td>${mils?mils.galsPerMil:"—"}</td><td>${mils?mils.lbsPerMil:"—"}</td><td style="font-weight:700">${mils?mils.mils:"—"}</td></tr>`;
      });});
      let tl=0,tu=0; coatingDays.forEach(d=>(d.runs||[]).forEach(r=>{tl+=r.totalLbsLoaded||0;tu+=r.totalLbsUnloaded||0;}));
      const ta=tl-tu,mils=Calc.coatingMils(proj,ta);
      body+=`<tr style="background:#f0f0f0;font-weight:700"><td colspan="9">TOTAL</td><td>${ta.toLocaleString()} lbs</td><td>${mils?mils.sqFt+"ft²":"—"}</td><td>${mils?mils.galsPerMil:"—"}</td><td>${mils?mils.lbsPerMil:"—"}</td><td style="font-size:13px">${mils?mils.mils+" mils":"—"}</td></tr></tbody></table>`;
    } else {
      body+=`<h2>Coating Run Sheet</h2><p style="color:#888">No coating data recorded.</p>`;
    }

    // ── JSAs — full detail, every field ─────────────────────────────────────
    body+=`<h2>JSA Details (${(jsas||[]).length} JSAs)</h2>`;
    if(!jsas||jsas.length===0){ body+=`<p style="color:#888">No JSAs recorded.</p>`; }
    else { body+=`<pre style="white-space:pre-wrap;font-family:'Courier New',monospace;font-size:9px;line-height:1.5;background:#fafafa;border:1px solid #ddd;border-radius:4px;padding:10px">${this.buildJSAText(jsas).replace(/</g,"&lt;")}</pre>`; }

    // ── Deliveries, Pick-ups & Fuel ──────────────────────────────────────────
    body+=`<h2>Deliveries, Pick-Ups &amp; Fuel (${(deliveries||[]).length} entries)</h2>`;
    if(!deliveries||deliveries.length===0){ body+=`<p style="color:#888">No delivery/pickup/fuel entries recorded.</p>`; }
    else {
      body+=`<table><thead><tr><th>Kind</th><th>Type</th><th>Delivered/Recorded</th><th>Picked Up</th><th>Quantity</th><th>Notes</th></tr></thead><tbody>`;
      [...deliveries].sort((a,b)=>(a.deliveredAt||a.recordedAt||0)-(b.deliveredAt||b.recordedAt||0)).forEach(d=>{
        const kindLbl=d.kind==="delivery"?"🚛 Delivery":d.kind==="fuel"?"⛽ Fuel":"📤 Pick-Up";
        const when=new Date(d.deliveredAt||d.recordedAt||0).toLocaleString("en-US");
        const pickedUp=d.pickedUpAt?new Date(d.pickedUpAt).toLocaleString("en-US"):(d.kind==="delivery"?"Still on site":"—");
        body+=`<tr><td>${kindLbl}</td><td>${d.type||"—"}</td><td>${when}</td><td>${pickedUp}</td><td>${d.quantity?d.quantity+(d.kind==="fuel"?" gal":""):"—"}</td><td>${d.notes||"—"}</td></tr>`;
      });
      body+=`</tbody></table>`;
    }

    // ── Compressor / Equipment Hours ─────────────────────────────────────────
    const comps=(compData&&compData.comps)||[];
    body+=`<h2>Compressor / Equipment Hours (${comps.length} unit${comps.length!==1?"s":""})</h2>`;
    if(comps.length===0){ body+=`<p style="color:#888">No compressor data recorded.</p>`; }
    else {
      comps.forEach(c=>{
        const now=Date.now();
        const sessions=c.sessions||[];
        const allSessions=c.running&&c.runSince?[...sessions,{start:c.runSince,end:now}]:sessions;
        const totalMs=allSessions.reduce((sum,s)=>sum+((s.end||now)-s.start),0);
        const totalHrs=(totalMs/3600000).toFixed(2);
        body+=`<div class="section"><b>${c.name}</b> — ${c.running?'<span style="color:#c0392b;font-weight:700">Currently Running</span>':"Off"}<br>
        <span class="kv">Meter Start Hours: ${c.startHours!=null?c.startHours:"—"}</span><span class="kv">Meter Start Date: ${c.startDate||"—"}</span><span class="kv">Logged Time: ${totalHrs} hrs</span>`;
        if(allSessions.length>0){
          body+=`<div style="margin-top:6px;font-size:9px;color:#555">${allSessions.map(s=>`${new Date(s.start).toLocaleString("en-US")} → ${s.end?new Date(s.end).toLocaleString("en-US"):"(running)"}`).join(" &nbsp;|&nbsp; ")}</div>`;
        }
        body+=`</div>`;
      });
    }

    // ── Inspections (DFT) ─────────────────────────────────────────────────────
    body+=`<h2>Final Inspection / DFT Readings</h2>`;
    if(inspections&&inspections.length>0) body+=this.buildInspectionHTML(inspections);
    else body+=`<p style="color:#888">No inspection data recorded.</p>`;

    // ── Checklist ─────────────────────────────────────────────────────────────
    body+=`<h2>Checklist</h2>`;
    if(!checklist||checklist.length===0){ body+=`<p style="color:#888">No checklist data recorded.</p>`; }
    else {
      checklist.forEach(sec=>{
        body+=`<h3>${sec.title}</h3><table><thead><tr><th style="width:24px"></th><th>Item</th><th>Notes</th></tr></thead><tbody>`;
        (sec.items||[]).forEach(it=>{
          body+=`<tr${it.checked?' style="color:#888"':''}><td style="text-align:center">${it.checked?"✓":"☐"}</td><td>${it.text}</td><td>${it.notes||""}</td></tr>`;
        });
        body+=`</tbody></table>`;
      });
    }

    // ── Daily Notes ───────────────────────────────────────────────────────────
    const nwt=(dailyNotes||[]).filter(n=>n.text);
    body+=`<h2>Daily Notes</h2>`;
    if(nwt.length===0){ body+=`<p style="color:#888">No daily notes recorded.</p>`; }
    else { nwt.sort((a,b)=>new Date(a.date)-new Date(b.date)).forEach(n=>{body+=`<h3>${n.date}</h3><p style="white-space:pre-wrap;line-height:1.7">${n.text}</p>`;}); }

    // ── All Photos — every photo, regardless of report flags ────────────────
    body+=`<h2>Photos (${(photos||[]).length} total)</h2>`;
    if(!photos||photos.length===0){ body+=`<p style="color:#888">No photos recorded.</p>`; }
    else {
      body+=`<div class="photo-grid">`;
      photos.forEach(p=>{
        const ts=new Date(p.timestamp).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})+" "+new Date(p.timestamp).toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit",hour12:true});
        const imgSrc=(photoBase64Map&&photoBase64Map[p.id])||p.storageUrl||p.dataUrl||"";
        const flags=[p.addToDaily?"Daily":null,p.addToFinal?"Final":null].filter(Boolean).join(", ");
        if(imgSrc)body+=`<div class="photo-card"><img src="${imgSrc}" /><div class="photo-caption"><div style="font-size:9px;color:#888;font-weight:700;margin-bottom:2px">${ts}${flags?" · "+flags:""}</div>${p.description?`<div style="font-size:12px;color:#333">${p.description}</div>`:""}</div></div>`;
      });
      body+=`</div>`;
    }

    return body;
  },

  async emailArchive(proj, runs, dailyNotes, coatingDays, jsas, deliveries, compData, inspections, checklist, photos) {
    const CSS=`
      @page{margin:0;size:portrait}
      body{font-family:Arial,sans-serif;font-size:11px;margin:0;padding:14mm 14mm 14mm 14mm;color:#222;line-height:1.5;-webkit-print-color-adjust:exact;print-color-adjust:exact}
      a{color:inherit;text-decoration:none;pointer-events:none}
      h1{font-size:18px}
      h2{font-size:14px;border-bottom:2px solid #b05000;padding-bottom:3px;margin:14px 0 8px}
      h3{font-size:12px;color:#b05000;margin:8px 0 4px}
      table{width:100%;border-collapse:collapse;margin-bottom:10px}
      th{background:#1a2535;color:#fff;padding:3px 4px;font-size:7px;-webkit-print-color-adjust:exact;print-color-adjust:exact}
      td{padding:2px 4px;border-bottom:1px solid #f0f0f0;font-size:8px;white-space:nowrap}
      .logo{font-size:14px;font-weight:900;color:#b05000}
      .meta{font-size:11px;color:#555;margin-bottom:14px}
      .section{margin-bottom:16px;padding:10px;border:1px solid #ddd;border-radius:4px}
      .kv{display:inline-block;margin-right:18px;margin-bottom:3px}
      .photo-grid{display:block;margin-bottom:16px}
      .photo-card{display:block;width:100%;border:1px solid #ddd;border-radius:6px;overflow:hidden;margin-bottom:14px;break-inside:avoid;page-break-inside:avoid}
      .photo-card img{width:100%;max-height:320px;object-fit:contain;display:block}
      .photo-caption{padding:6px 10px;background:#f9f9f9;border-top:1px solid #eee}
      .no-print{display:block}
      @media print{
        @page{margin:0;size:portrait}
        body{padding:10mm 12mm 10mm 12mm}
        .no-print{display:none!important}
        table{page-break-inside:auto}
        tr{page-break-inside:avoid;break-inside:avoid}
        h2{page-break-after:avoid;break-after:avoid}
        .photo-card{break-inside:avoid;page-break-inside:avoid}
      }
    `;
    const subj=`Complete Archive - ${proj.projectNumber||""} - ${proj.client||""}`;
    // Open loading window immediately so browser doesn't block it as a popup
    const w=window.open("","_blank");
    w.document.write(`<!DOCTYPE html><html><head><title>${subj}</title><style>${CSS}</style></head><body><div style="text-align:center;padding:60px 20px;font-family:Arial,sans-serif"><div style="font-size:16px;font-weight:700;color:#b05000;margin-bottom:12px">⏳ Building Complete Archive…</div><div style="font-size:12px;color:#666">Fetching all photos — this may take a moment for large projects</div></div></body></html>`);
    w.document.close();
    // Archive includes EVERY photo, regardless of daily/final flags
    const photoBase64Map=await this.fetchPhotosAsBase64(photos||[]);
    const htmlBody=this.buildArchiveHTML(proj,runs,dailyNotes,coatingDays,jsas,deliveries,compData,inspections,checklist,photos,photoBase64Map);
    w.document.open();
    w.document.write(`<!DOCTYPE html><html><head><title>${subj}</title><style>${CSS}</style></head><body><div class="no-print" style="text-align:right;margin-bottom:16px;padding:8px;background:#f5f5f5;border-radius:6px"><b style="margin-right:16px">Complete Archive — ${proj.projectNumber||""}</b><button onclick="window.print()" style="background:#b05000;color:#fff;border:none;padding:8px 16px;border-radius:6px;font-size:12px;cursor:pointer">🖨 Print / Save PDF</button><button onclick="window.close()" style="background:#eee;border:none;padding:8px 14px;border-radius:6px;font-size:12px;cursor:pointer;margin-left:8px">Close</button></div>${htmlBody}</body></html>`);
    w.document.close();
  },

  buildJSAHTML(proj, jsa) {
    const fire=Object.entries(jsa.fire||{}).filter(([,v])=>v).map(([k])=>k);
    const ppe=Object.entries(jsa.ppe||{}).filter(([,v])=>v).map(([k])=>k);
    const energy=Object.entries(jsa.energy||{}).filter(([,v])=>v).map(([k])=>k);
    const tasks = jsa.tasks || [];
    const tasksHTML = tasks.length>0
      ? "<h2>Tasks &amp; Hazard Mitigations</h2>" + tasks.map((task,ti)=>{
          const label = task.type==="Manual Entry" ? (task.customLabel||"Manual Entry") : task.type;
          const hazardRows = (task.hazards||[]).map((h,hi)=>
            "<tr style='border-bottom:1px solid #eee'>"
            +"<td style='padding:8px;font-weight:700;color:#b05000;width:30px'>"+String.fromCharCode(65+hi)+"</td>"
            +"<td style='padding:8px;width:40%'>"+h.name+"</td>"
            +"<td style='padding:8px'>"+(h.mitigation||"—")+"</td>"
            +"</tr>"
          ).join("");
          return "<div style='margin-bottom:14px;border:1px solid #ddd;border-radius:4px;overflow:hidden'>"
            +"<div style='background:#1a2535;color:#fff;padding:8px 12px;font-size:12px;font-weight:700'>Task "+(ti+1)+": "+label+"</div>"
            +(hazardRows
              ? "<table style='width:100%;border-collapse:collapse;font-size:11px'>"
                +"<thead><tr style='background:#f5f5f5'><th style='padding:6px 8px;text-align:left;width:30px'>#</th><th style='padding:6px 8px;text-align:left;width:40%'>Hazard</th><th style='padding:6px 8px;text-align:left'>Mitigation</th></tr></thead>"
                +"<tbody>"+hazardRows+"</tbody></table>"
              : "<p style='padding:8px 12px;font-size:11px;color:#888;font-style:italic'>No hazards selected</p>")
            +"</div>";
        }).join("")
      : "";
    return `<div class="logo">INTERNAL PIPELINE SERVICES</div>
    <div class="meta">2440-B Chambers St. · Venus, TX 76084 · (817) 539-9764</div>
    <h1>Job Safety Analysis (JSA) & Daily Toolbox Talk</h1>
    <div class="section">
      <span class="kv"><b>Date:</b> ${jsa.date||"—"}</span><span class="kv"><b>Supervisor:</b> ${jsa.supervisor||"—"}</span><span class="kv"><b>Client:</b> ${jsa.client||proj.client||"—"}</span><br>
      <span class="kv"><b>Location:</b> ${jsa.location||proj.location||"—"}</span><br>
      <span class="kv"><b>Task Start:</b> ${jsa.taskStartTime||"—"}</span><span class="kv"><b>Task End:</b> ${jsa.taskEndTime||"—"}</span>
    </div>
    ${tasksHTML}
    ${fire.length>0?`<h2>Fire Protection</h2><p>${fire.join(" · ")}</p>`:""}
    ${ppe.length>0?`<h2>PPE Required</h2><p>${ppe.join(" · ")}</p>`:""}
    ${energy.length>0?`<h2>Energy Control</h2><p>${energy.join(" · ")}</p>`:""}
    <h2>Pre-Work Job Safety Review</h2>
    <table><thead><tr><th style="width:65%">Question</th><th>Response</th></tr></thead><tbody>
    ${JSA_PREWORK.map((q,i)=>`<tr><td style="font-size:10px">${q}</td><td style="font-weight:700;text-align:center;color:${jsa.prework?.[i]==="No"?"#cc2222":jsa.prework?.[i]==="Yes"?"#006600":"#999"}">${jsa.prework?.[i]||"—"}</td></tr>`).join("")}
    </tbody></table>
    ${jsa.emergencyExt||jsa.fireExt?`<p style="margin-bottom:10px;font-size:11px"><b>In Event of Emergency, Call Ext:</b> ${jsa.emergencyExt||"—"} &nbsp;&nbsp;&nbsp; <b>Fires Reported by Dialing Ext:</b> ${jsa.fireExt||"—"}</p>`:""}
    ${jsa.additionalComments?`<h2>Comments / Instructions</h2><p>${jsa.additionalComments}</p>`:""}
    <h2>Crew Sign-In</h2>
    <table><thead><tr><th>Name</th><th>Time</th></tr></thead><tbody>
    ${(jsa.crewSignIn||[]).map(s=>`<tr><td>${s.name}</td><td>${Fmt.timeShort(s.time)}</td></tr>`).join("")||`<tr><td colspan="2"><i>None recorded</i></td></tr>`}
    </tbody></table>
    <h2>Crew Sign-Out</h2>
    <table><thead><tr><th>Name</th><th>Time</th></tr></thead><tbody>
    ${(jsa.crewSignOut||[]).map(s=>`<tr><td>${s.name}</td><td>${Fmt.timeShort(s.time)}</td></tr>`).join("")||`<tr><td colspan="2"><i>None recorded</i></td></tr>`}
    </tbody></table>
    ${jsa.postJobOtherComments?`<h2>Post-Job Notes</h2><p>${jsa.postJobOtherComments}</p>`:""}`;
  },
  async emailDaily(proj, dayRuns, dayNote, dayDate, dayCoating, dayJSAs, inspections, photos, allJsas) {
    const CSS=`
      @page{margin:0;size:portrait}
      body{font-family:Arial,sans-serif;font-size:10px;margin:0;padding:12mm 12mm 12mm 12mm;color:#222;line-height:1.4;-webkit-print-color-adjust:exact;print-color-adjust:exact}
      a{color:inherit;text-decoration:none;pointer-events:none}
      h1{font-size:15px;margin:4px 0 2px}
      h2{font-size:12px;border-bottom:1.5px solid #b05000;padding-bottom:2px;margin:8px 0 4px;color:#b05000}
      h3{font-size:10px;color:#b05000;margin:4px 0 2px}
      table{width:100%;border-collapse:collapse;margin-bottom:6px}
      th{background:#1a2535;color:#fff;padding:3px 5px;font-size:8px;text-align:left;-webkit-print-color-adjust:exact;print-color-adjust:exact}
      td{padding:2px 5px;border-bottom:1px solid #eee;font-size:9px}
      .logo{font-size:13px;font-weight:900;color:#b05000;margin-bottom:1px}
      .meta{font-size:9px;color:#555;margin-bottom:6px}
      .section{margin-bottom:8px;padding:7px 10px;border:1px solid #ddd;border-radius:3px}
      .kv{display:inline-block;margin-right:14px;margin-bottom:2px}
      .photo-grid{display:block;margin-bottom:12px}
      .photo-card{display:block;width:100%;border:1px solid #ddd;border-radius:4px;overflow:hidden;margin-bottom:10px;break-inside:avoid;page-break-inside:avoid}
      .photo-card img{width:100%;max-height:260px;object-fit:contain;display:block}
      .photo-caption{padding:4px 6px;background:#f9f9f9;border-top:1px solid #eee}
      .no-print{display:block}
      @media print{
        @page{margin:0;size:portrait}
        body{padding:10mm 12mm 10mm 12mm}
        .no-print{display:none!important}
        tr{page-break-inside:avoid;break-inside:avoid}
        h2{page-break-after:avoid;break-after:avoid}
        .photo-card{break-inside:avoid;page-break-inside:avoid}
      }
    `;
    const title=`Daily Report - ${proj.client||""} - ${dayDate}`;
    // Open loading window immediately to avoid popup blocker
    const w=window.open("","_blank");
    w.document.write(`<!DOCTYPE html><html><head><title>${title}</title><style>${CSS}</style></head><body><div style="text-align:center;padding:60px 20px;font-family:Arial,sans-serif"><div style="font-size:16px;font-weight:700;color:#b05000;margin-bottom:12px">⏳ Building Report…</div><div style="font-size:12px;color:#666">Fetching photos — this may take a moment</div></div></body></html>`);
    w.document.close();
    // Pre-fetch all daily photos as embedded base64
    const dailyPhotos=(photos||[]).filter(p=>p.addToDaily);
    const photoBase64Map=await this.fetchPhotosAsBase64(dailyPhotos);
    const htmlBody=this.buildDailyHTML(proj,dayRuns,dayNote,dayDate,dayCoating,dayJSAs,inspections,photos,allJsas,photoBase64Map);
    w.document.open();
    w.document.write(`<!DOCTYPE html><html><head><title>${title}</title><style>${CSS}</style></head><body><div class="no-print" style="text-align:right;margin-bottom:16px;padding:8px;background:#f5f5f5;border-radius:6px"><b style="margin-right:16px">Daily Report — ${dayDate}</b><button onclick="window.print()" style="background:#b05000;color:#fff;border:none;padding:8px 16px;border-radius:6px;font-size:12px;cursor:pointer">🖨 Print / Save PDF</button><button onclick="window.close()" style="background:#eee;border:none;padding:8px 14px;border-radius:6px;font-size:12px;cursor:pointer;margin-left:8px">Close</button></div>${htmlBody}</body></html>`);
    w.document.close();
  },

  async emailFinal(proj, runs, dailyNotes, coatingDays, review, inspections, photos) {
    const CSS=`
      @page{margin:0;size:portrait}
      body{font-family:Arial,sans-serif;font-size:11px;margin:0;padding:14mm 14mm 14mm 14mm;color:#222;line-height:1.5;-webkit-print-color-adjust:exact;print-color-adjust:exact}
      a{color:inherit;text-decoration:none;pointer-events:none}
      h1{font-size:18px}
      h2{font-size:14px;border-bottom:2px solid #b05000;padding-bottom:3px;margin:14px 0 8px}
      h3{font-size:12px;color:#b05000;margin:8px 0 4px}
      table{width:100%;border-collapse:collapse;margin-bottom:10px}
      th{background:#1a2535;color:#fff;padding:3px 4px;font-size:7px;-webkit-print-color-adjust:exact;print-color-adjust:exact}
      td{padding:2px 4px;border-bottom:1px solid #f0f0f0;font-size:8px;white-space:nowrap}
      .logo{font-size:14px;font-weight:900;color:#b05000}
      .meta{font-size:11px;color:#555;margin-bottom:14px}
      .section{margin-bottom:16px;padding:10px;border:1px solid #ddd;border-radius:4px}
      .kv{display:inline-block;margin-right:18px;margin-bottom:3px}
      .photo-grid{display:block;margin-bottom:16px}
      .photo-card{display:block;width:100%;border:1px solid #ddd;border-radius:6px;overflow:hidden;margin-bottom:14px;break-inside:avoid;page-break-inside:avoid}
      .photo-card img{width:100%;max-height:320px;object-fit:contain;display:block}
      .photo-caption{padding:6px 10px;background:#f9f9f9;border-top:1px solid #eee}
      .no-print{display:block}
      @media print{
        @page{margin:0;size:portrait}
        body{padding:10mm 12mm 10mm 12mm}
        .no-print{display:none!important}
        table{page-break-inside:auto}
        tr{page-break-inside:avoid;break-inside:avoid}
        h2{page-break-after:avoid;break-after:avoid}
        .photo-card{break-inside:avoid;page-break-inside:avoid}
      }
    `;
    const subj=`Final Report - ${proj.client||""} - ${proj.diameter}" x ${proj.length}ft`;
    // Open loading window immediately so browser doesn't block it as a popup
    const w=window.open("","_blank");
    w.document.write(`<!DOCTYPE html><html><head><title>${subj}</title><style>${CSS}</style></head><body><div style="text-align:center;padding:60px 20px;font-family:Arial,sans-serif"><div style="font-size:16px;font-weight:700;color:#b05000;margin-bottom:12px">⏳ Building Report…</div><div style="font-size:12px;color:#666">Fetching photos — this may take a moment</div></div></body></html>`);
    w.document.close();
    // Pre-fetch all final-report photos as embedded base64
    const finalPhotos=(photos||[]).filter(p=>p.addToFinal);
    const photoBase64Map=await this.fetchPhotosAsBase64(finalPhotos);
    const htmlBody=this.buildFinalHTML(proj,runs,dailyNotes,coatingDays,inspections,review,photos,photoBase64Map);
    w.document.open();
    w.document.write(`<!DOCTYPE html><html><head><title>${subj}</title><style>${CSS}</style></head><body><div class="no-print" style="text-align:right;margin-bottom:16px;padding:8px;background:#f5f5f5;border-radius:6px"><b style="margin-right:16px">Final Report — ${proj.client||""}</b><button onclick="window.print()" style="background:#b05000;color:#fff;border:none;padding:8px 16px;border-radius:6px;font-size:12px;cursor:pointer">🖨 Print / Save PDF</button><button onclick="window.close()" style="background:#eee;border:none;padding:8px 14px;border-radius:6px;font-size:12px;cursor:pointer;margin-left:8px">Close</button></div>${htmlBody}</body></html>`);
    w.document.close();
  },

  emailJSA(proj, jsa) {
    const CSS=`@page{margin:0}body{font-family:Arial,sans-serif;font-size:11px;margin:0;padding:12mm 14mm 12mm 14mm;color:#222;line-height:1.5;-webkit-print-color-adjust:exact;print-color-adjust:exact}a{color:inherit;text-decoration:none;pointer-events:none}h1{font-size:18px}h2{font-size:14px;border-bottom:2px solid #b05000;padding-bottom:3px;margin:14px 0 8px}table{width:100%;border-collapse:collapse;margin-bottom:10px}th{background:#1a2535;color:#fff;padding:5px 6px;font-size:10px;-webkit-print-color-adjust:exact;print-color-adjust:exact}td{padding:4px 6px;border-bottom:1px solid #eee;font-size:10px}.logo{font-size:14px;font-weight:900;color:#b05000}.meta{font-size:11px;color:#555;margin-bottom:14px}.section{margin-bottom:16px;padding:10px;border:1px solid #ddd;border-radius:4px}.kv{display:inline-block;margin-right:18px;margin-bottom:3px}.no-print{display:block}@media print{@page{margin:0}.no-print{display:none!important}tr{page-break-inside:avoid;break-inside:avoid}}`;
    const htmlBody=this.buildJSAHTML(proj,jsa);
    const w=window.open("","_blank");
    w.document.write(`<!DOCTYPE html><html><head><title>JSA - ${proj.client||""} - ${jsa.date}</title><style>${CSS}</style></head><body><div class="no-print" style="text-align:right;margin-bottom:16px;padding:8px;background:#f5f5f5;border-radius:6px"><b style="margin-right:16px">JSA — ${jsa.date||""}</b><button onclick="window.print()" style="background:#b05000;color:#fff;border:none;padding:8px 16px;border-radius:6px;font-size:12px;cursor:pointer">🖨 Print / Save PDF</button><button onclick="window.close()" style="background:#eee;border:none;padding:8px 14px;border-radius:6px;font-size:12px;cursor:pointer;margin-left:8px">Close</button></div>${htmlBody}</body></html>`);
    w.document.close();
  }
};

// ======== page-projects.js ========
function ProjectsPage({projects,onSelect,onCreate,onDelete}) {
  return (
    <div style={{padding:"24px 16px",maxWidth:CONTAINER_MAX,margin:"0 auto",minHeight:"100vh",background:"var(--bg)"}}>
      <style>{CSS}</style>
      <link href="https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700;800;900&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet" />
      <div style={{textAlign:"center",marginBottom:32}}>
        {typeof LOGO_DATA_URL!=="undefined"&&<img src={LOGO_DATA_URL} alt="IPS" style={{width:80,height:80,marginBottom:12}} />}
        <div style={{fontSize:26,fontWeight:900,fontFamily:"var(--display)",letterSpacing:"-0.02em"}}>IPS-PROJECT</div>
        <div style={{fontSize:12,color:"var(--muted)"}}>Internal Pipeline Services</div>
      </div>
      <button onClick={onCreate} style={{...S.bp,marginBottom:24}}>+ New Project</button>
      {projects.length===0&&<div style={{textAlign:"center",color:"var(--dim)",padding:24}}>No projects yet</div>}
      {projects.length>0&&<div style={{fontSize:11,color:"var(--muted)",fontWeight:700,textTransform:"uppercase",marginBottom:8}}>Swipe left to delete</div>}
      {[...projects].reverse().map(p=>(
        <SwipeRow key={p.id} onDelete={()=>onDelete(p.id)}>
          <div onClick={()=>onSelect(p.id)} style={{...S.card,cursor:"pointer",marginBottom:0,borderRadius:14}}>
            <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:4}}>
              <div style={{display:"flex",alignItems:"center",gap:8}}>
                <div style={{fontWeight:800,fontSize:15,color:"var(--accent)"}}>{p.projectNumber} — {p.client||"(No client)"}</div>
                {p._sectionNum && <span style={{fontSize:9,color:"var(--muted)",fontWeight:800,background:"rgba(255,165,0,0.1)",border:"1px solid rgba(255,165,0,0.25)",borderRadius:6,padding:"2px 7px",textTransform:"uppercase",letterSpacing:"0.08em"}}>Section {p._sectionNum}</span>}
              </div>
              {p.closed&&<span style={{fontSize:10,color:"#ff4444",fontWeight:800,background:"rgba(255,68,68,0.12)",border:"1px solid rgba(255,68,68,0.3)",borderRadius:6,padding:"2px 8px"}}>CLOSED</span>}
            </div>
            <div style={{fontSize:12,color:"var(--muted)"}}>{p.diameter||"?"}" × {Number(p.length||0).toLocaleString()}ft · {p.location||"—"}</div>
            <div style={{fontSize:11,color:"var(--dim)",marginTop:2}}>{(p.runs||[]).length} runs · Job #: {p.jobNumber||"—"}{p.startDate?" · "+p.startDate:""}{p.endDate?" → "+p.endDate:""}</div>
          </div>
        </SwipeRow>
      ))}
    </div>
  );
}

// ======== page-setup.js ========
function SetupPage({proj,onUpdate,onBack,onContinue,onClose,NavBar}) {
  const [emailInput,setEmailInput]=useState("");
  const [reviewEmailInput,setReviewEmailInput]=useState("");
  const [newPin,setNewPin]=useState("");
  const [pinMsg,setPinMsg]=useState("");
  const addEmail=()=>{const e=emailInput.trim();if(e&&!proj.emails?.includes(e)){onUpdate("emails",[...(proj.emails||[]),e]);setEmailInput("")}};
  const addReviewEmail=()=>{const e=reviewEmailInput.trim();if(e&&!(proj.reviewEmails||[]).includes(e)){onUpdate("reviewEmails",[...(proj.reviewEmails||[]),e]);setReviewEmailInput("")}};
  return (
    <div style={{padding:"12px 16px",maxWidth:CONTAINER_MAX,margin:"0 auto",paddingBottom:80}}>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:16}}>
        <button onClick={onBack} style={{...S.bs,padding:"8px 14px",fontSize:12,width:"auto"}}>← Projects</button>
        <div style={{fontSize:14,fontWeight:800}}>Project Setup</div>
        <button onClick={onContinue} style={{...S.bp,padding:"8px 18px",width:"auto",fontSize:12}}>Done →</button>
      </div>
      {proj.closed&&<div style={{...S.card,background:"rgba(255,68,68,0.08)",border:"1px solid rgba(255,68,68,0.3)",padding:"10px 14px",marginBottom:8,textAlign:"center",color:"#ff6b6b",fontWeight:700,fontSize:13}}>🔒 Project Closed</div>}
      {!proj.closed&&<button onClick={onClose} style={{...S.bs,width:"100%",marginBottom:12,padding:"12px",color:"#ff6b6b",border:"1px solid rgba(255,68,68,0.3)"}}>🔒 Close Project</button>}
      {[["Project #","projectNumber"],["Job Number","jobNumber"],["Client","client"],["Location","location"],["Product Type","productType"],["Pipeline Length (ft)","length","number","numeric"],["Reference Diameter (in)","diameter","number","decimal"],["Actual ID (in)","actualID","number","decimal"],["Default Tank","defaultTank"]].map(([lbl,fld,tp,im])=>(
        <div key={fld} style={{...S.card,padding:"10px 14px",marginBottom:8}}>
          <Inp label={lbl} type={tp} inputMode={im} value={proj[fld]} onChange={v=>onUpdate(fld,v)} />
        </div>
      ))}
      <div style={{...S.card,padding:"10px 14px",marginBottom:8}}>
        <label style={S.lb}>Number of Sections</label>
        <div style={{display:"flex",gap:8,flexWrap:"wrap"}}>
          {[1,2,3,4,5,6].map(n=>(
            <button key={n} onClick={()=>onUpdate("numSections",n)}
              style={{padding:"9px 18px",borderRadius:10,border:`1px solid ${(proj.numSections||1)===n?"var(--accent)":"var(--border)"}`,background:(proj.numSections||1)===n?"rgba(255,165,0,0.15)":"transparent",color:(proj.numSections||1)===n?"var(--accent)":"var(--muted)",fontSize:14,fontWeight:700,cursor:"pointer",fontFamily:"var(--font)"}}>
              {n}
            </button>
          ))}
        </div>
        {(proj.numSections||1) > 1 && (
          <div style={{marginTop:10,fontSize:11,color:"var(--muted)"}}>
            Crew will be prompted to select a section after logging in. Each section has its own independent runs, chemicals, and reports.
          </div>
        )}
      </div>
      <div style={{...S.card,padding:"10px 14px",marginBottom:8}}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <Inp label="Start Date" value={proj.startDate||""} onChange={v=>onUpdate("startDate",v)} placeholder="MM/DD/YYYY" />
          <Inp label="End Date" value={proj.endDate||""} onChange={v=>onUpdate("endDate",v)} placeholder="MM/DD/YYYY" />
        </div>
      </div>
      <div style={{...S.card,padding:"10px 14px",marginBottom:8}}>
        <Inp label="Primary Email (reports)" value={proj.email} onChange={v=>onUpdate("email",v)} />
      </div>
      <div style={{...S.card,padding:"10px 14px",marginBottom:8}}>
        <div style={S.ct}>Additional Recipients</div>
        <div style={{display:"flex",gap:8,marginBottom:8}}>
          <input value={emailInput} onChange={e=>setEmailInput(e.target.value)} onKeyDown={e=>e.key==="Enter"&&addEmail()} placeholder="email@example.com" style={{...S.inp,flex:1}} />
          <button onClick={addEmail} style={{...S.ba,width:"auto",padding:"10px 16px",fontSize:13}}>Add</button>
        </div>
        {(proj.emails||[]).map((e,i)=>(
          <div key={i} style={{display:"flex",justifyContent:"space-between",alignItems:"center",padding:"6px 10px",background:"rgba(255,165,0,0.06)",borderRadius:8,marginBottom:4}}>
            <span style={{fontSize:12,color:"var(--text)"}}>{e}</span>
            <button onClick={()=>onUpdate("emails",(proj.emails||[]).filter((_,j)=>j!==i))} style={{background:"none",border:"none",color:"#ff4444",cursor:"pointer",fontSize:14}}>✕</button>
          </div>
        ))}
      </div>
      <div style={{...S.card,padding:"10px 14px"}}>
        <div style={S.ct}>Review Email Recipients</div>
        <div style={{fontSize:11,color:"var(--muted)",marginBottom:8}}>Emails that will receive the final customer review</div>
        <div style={{display:"flex",gap:8,marginBottom:8}}>
          <input value={reviewEmailInput} onChange={e=>setReviewEmailInput(e.target.value)} onKeyDown={e=>e.key==="Enter"&&addReviewEmail()} placeholder="review@example.com" style={{...S.inp,flex:1}} />
          <button onClick={addReviewEmail} style={{...S.ba,width:"auto",padding:"10px 16px",fontSize:13}}>Add</button>
        </div>
        {(proj.reviewEmails||[]).map((e,i)=>(
          <div key={i} style={{display:"flex",justifyContent:"space-between",alignItems:"center",padding:"6px 10px",background:"rgba(255,165,0,0.06)",borderRadius:8,marginBottom:4}}>
            <span style={{fontSize:12,color:"var(--text)"}}>{e}</span>
            <button onClick={()=>onUpdate("reviewEmails",(proj.reviewEmails||[]).filter((_,j)=>j!==i))} style={{background:"none",border:"none",color:"#ff4444",cursor:"pointer",fontSize:14}}>✕</button>
          </div>
        ))}
      </div>
      <div style={{...S.card,padding:"10px 14px",marginTop:8}}>
        <div style={S.ct}>Manager PIN</div>
        <div style={{fontSize:11,color:"var(--muted)",marginBottom:10}}>Full access to all projects and tabs. Crew log in with their project number.</div>
        {pinMsg&&<div style={{color:"#00e676",fontSize:12,fontWeight:700,marginBottom:8}}>{pinMsg}</div>}
        <div style={{display:"flex",gap:8}}>
          <input type="password" inputMode="numeric" maxLength={4} value={newPin} onChange={e=>setNewPin(e.target.value.replace(/\D/g,"").slice(0,4))} placeholder="4-digit PIN" style={{...S.inp,flex:1,letterSpacing:"0.3em",fontSize:20,textAlign:"center"}} />
          <button onClick={async()=>{if(newPin.length!==4)return;await Storage.setManagerPin(newPin);setNewPin("");setPinMsg("Manager PIN updated");setTimeout(()=>setPinMsg(""),2000);}} disabled={newPin.length!==4} style={{...S.ba,width:"auto",padding:"10px 16px",fontSize:13,opacity:newPin.length===4?1:0.4}}>Save</button>
        </div>
      </div>
    </div>
  );
}

// ======== page-runs.js ========
// ═══ INLINE PASS EDITOR — enter receive data per shuttle pass during active run ═══
function InlinePassEditor({passes, onUpdatePass}) {
  const [activePassIdx, setActivePassIdx] = React.useState(passes.length - 1);
  const [passPopup, setPassPopup] = React.useState(null);
  const [solidsManual, setSolidsManual] = React.useState("");

  React.useEffect(() => { setActivePassIdx(passes.length - 1); }, [passes.length]);

  const p = passes[activePassIdx] || {};

  return (
    <div style={{background:"rgba(255,171,0,0.04)",border:"1px solid rgba(255,171,0,0.2)",borderRadius:10,padding:"10px 12px",marginBottom:12}}>
      <div style={{fontSize:10,color:"var(--accent)",fontWeight:800,textTransform:"uppercase",marginBottom:8}}>Completed Pass — Receive Data</div>
      <div style={{display:"flex",gap:6,marginBottom:10,flexWrap:"wrap"}}>
        {passes.map((p,pi)=>(
          <button key={pi} onClick={()=>setActivePassIdx(pi)} style={{background:activePassIdx===pi?"var(--accent)":"rgba(255,171,0,0.1)",border:"1px solid rgba(255,171,0,0.3)",borderRadius:8,color:activePassIdx===pi?"#000":"var(--accent)",fontSize:11,fontWeight:700,padding:"5px 10px",cursor:"pointer",fontFamily:"var(--font)"}}>
            Pass {pi+1}
          </button>
        ))}
      </div>
      <div style={{fontSize:10,color:"var(--muted)",marginBottom:8}}>
        {p.direction&&p.direction.startsWith("Launch")?"L→R":"R→L"} · {Fmt.timeShort(p.launchTime)} → {Fmt.timeShort(p.receiveTime)} · {Fmt.duration(p.duration)}
      </div>
      <div style={{display:"flex",gap:8,marginBottom:4}}>
        <div style={{flex:1}}>
          <label style={S.lb}>% Solids</label>
          <button onClick={()=>setPassPopup("solids")} style={{...S.ba,width:"100%",padding:"10px 8px",fontSize:14}}>{p.totalSolids||"NA"}</button>
        </div>
        <div style={{flex:1}}>
          <label style={S.lb}>% Acid</label>
          <input value={p.percentAcid||""} onChange={e=>onUpdatePass(activePassIdx,{percentAcid:e.target.value})} placeholder="e.g. 2.5" style={{...S.inp,fontSize:14,textAlign:"center"}} inputMode="decimal" />
        </div>
        <div style={{flex:1}}>
          <label style={S.lb}>Color</label>
          <button onClick={()=>setPassPopup("color")} style={{...S.ba,width:"100%",padding:"10px 8px",fontSize:14}}>{p.solidColor||"NA"}</button>
        </div>
      </div>
      {passPopup==="solids"&&<PopupMenu title="% Solids" options={["Trace","<1","1.5","2","2.5","3","3.5","4","5","Manual"]} onSelect={v=>{if(v==="Manual"){setSolidsManual("");setPassPopup("solidsManual")}else{onUpdatePass(activePassIdx,{totalSolids:v});setPassPopup(null)}}} onClose={()=>setPassPopup(null)} />}
      {passPopup==="solidsManual"&&<PopupMenu title="Manual Solids" options={[]} onSelect={()=>{}} onClose={()=>setPassPopup(null)} showManual manualLabel="Enter %" manualValue={solidsManual} onManualChange={setSolidsManual} onManualConfirm={()=>{onUpdatePass(activePassIdx,{totalSolids:solidsManual});setPassPopup(null)}} />}
      {passPopup==="color"&&<PopupMenu title="Solid Color" options={SOLID_COLORS} onSelect={v=>{onUpdatePass(activePassIdx,{solidColor:v});setPassPopup(null)}} onClose={()=>setPassPopup(null)} />}
    </div>
  );
}

function RunsPage({proj,runs,activeRun,updateActiveRun,editingRun,setER,showPrompt,paused,setPaused,elapsed,setElapsed,pausedTotal,setPT,pauseRef,onSaveRun,onSavePastRun,onStartNew,onDeleteRun,onDuplicateRun,onClearEditingRun,onClearRun,setRuns,NavBar}) {

  const [editPassRun, setEditPassRun] = React.useState(null);
  const [editPassData, setEditPassData] = React.useState({});
  const [passPopup, setPassPopup] = React.useState(null);
  const [passManual, setPassManual] = React.useState("");

  const hLaunch=()=>{
    // Hard-reset all pause state first — prevents stale pausedTotal from a
    // previous run or accidental pause carrying over into this run's duration.
    setPaused(false); setPT(0); pauseRef.current=null;
    const launchTime = Date.now();
    updateActiveRun({launchTime, pausedDuration:0});
  };

  const hPause=()=>{
    if(paused){
      const pausedMs=Date.now()-pauseRef.current;
      setPT(p=>p+pausedMs);
      pauseRef.current=null;
      setPaused(false);
      // Rebase launchTime so elapsed continues correctly
      updateActiveRun({launchTime: activeRun.launchTime + pausedMs});
    }else{
      pauseRef.current=Date.now();
      setPaused(true);
    }
  };

  const hReceive=()=>{
    // Build true paused total: local state + any active pause in progress.
    // Guard: if pausedTotal is somehow stale (e.g. app reloaded mid-run on a
    // different device), cap it at receiveTime-launchTime so duration can't go negative.
    let tp=pausedTotal;if(paused&&pauseRef.current){tp+=Date.now()-pauseRef.current;pauseRef.current=null}
    const receiveTime=Date.now();
    const rawDiff=activeRun.launchTime?receiveTime-activeRun.launchTime:0;
    // Never let pausedTotal exceed the raw elapsed — prevents stale carry-over
    if(tp>rawDiff) tp=0;
    setPaused(false);setPT(tp);
    const duration=rawDiff>0?rawDiff-tp:0;
    if(activeRun.shuttleMode){
      const curDir=activeRun.direction;
      const nextDir=curDir.startsWith("Launch")?"Receive \u2192 Launch":"Launch \u2192 Receive";
      const passContactTime=computeContactTime(duration,activeRun.chemVolume,proj);
      const newPass={direction:curDir,launchTime:activeRun.launchTime,receiveTime,duration,pausedDuration:tp,contactTime:passContactTime,totalSolids:activeRun._passSolids||"NA",percentAcid:activeRun._passAcid||"NA",solidColor:activeRun._passColor||"NA"};
      const passes=[...(activeRun.shuttlePasses||[]),newPass];
      updateActiveRun({shuttlePasses:passes,direction:nextDir,launchTime:null,_shuttleReceiveTime:receiveTime,_passSolids:"NA",_passAcid:"NA",_passColor:"NA",pausedDuration:0});
      setPT(0);
    } else {
      updateActiveRun({receiveTime,pausedDuration:tp,duration});
    }
  };

  const hEndShuttle=()=>{
    let tp=pausedTotal;if(paused&&pauseRef.current){tp+=Date.now()-pauseRef.current;pauseRef.current=null}
    const receiveTime=Date.now();
    const rawDiff=activeRun.launchTime?receiveTime-activeRun.launchTime:0;
    if(tp>rawDiff) tp=0;
    setPaused(false);setPT(tp);
    const duration=rawDiff>0?rawDiff-tp:0;
    const passContactTime=computeContactTime(duration,activeRun.chemVolume,proj);
    const newPass={direction:activeRun.direction,launchTime:activeRun.launchTime,receiveTime,duration,pausedDuration:tp,contactTime:passContactTime,totalSolids:activeRun._passSolids||"NA",percentAcid:activeRun._passAcid||"NA",solidColor:activeRun._passColor||"NA"};
    const passes=[...(activeRun.shuttlePasses||[]),newPass];
    const totalDur=passes.reduce((s,p)=>s+(p.duration||0),0);
    const firstPassDir=passes[0]?.direction||activeRun.direction;
    updateActiveRun({receiveTime,duration:totalDur,shuttlePasses:passes,shuttleComplete:true,direction:firstPassDir});
  };
  // End shuttle between passes (after a receive, before the next launch)
  const hEndShuttleBetweenPasses=()=>{
    const passes=activeRun.shuttlePasses||[];
    const totalDur=passes.reduce((s,p)=>s+(p.duration||0),0);
    const lastReceiveTime=activeRun._shuttleReceiveTime||Date.now();
    const firstPassDir=passes[0]?.direction||activeRun.direction;
    updateActiveRun({receiveTime:lastReceiveTime,duration:totalDur,shuttleComplete:true,launchTime:null,direction:firstPassDir});
  };

  function computeContactTime(durationMs, vol, proj){
    const dm=Calc.calcDiam(proj),gpf=Calc.galPerFt(dm),bl=vol&&gpf>0?vol/gpf:0;
    const pl=parseFloat(proj.length)||0,spd=(durationMs>0&&pl>0)?pl/(durationMs/1000):0;
    const ct=spd>0?bl/spd:0;
    return ct>0?`${(ct/60).toFixed(1)} min`:"—";
  }

  const setMT=(field,ts)=>{
    if(!ts||!activeRun)return;
    const d=new Date(),[h,m,s]=ts.split(":").map(Number);d.setHours(h||0,m||0,s||0,0);const t=d.getTime();
    const updates={[field]:t};
    if(field==="launchTime"&&activeRun.receiveTime) updates.duration=activeRun.receiveTime-t-(activeRun.pausedDuration||0);
    if(field==="receiveTime"&&activeRun.launchTime) updates.duration=t-activeRun.launchTime-(activeRun.pausedDuration||0);
    updateActiveRun(updates);
    setPaused(false);
  };

  const updA=(f,v)=>{
    if(!activeRun) return;
    const updates={[f]:v};
    if(f==="chemVolume") updates.estVolumeOut=v;
    if(f==="chemType"){
      if(v==="HCL") updates.chemPercent="18.0%";
      else if(v==="H2O"||v==="Det"||v==="Solvent"||v==="Diesel"||v==="Inhib. H2O") updates.chemPercent="100%";
      else if(CHEMICAL_PRESETS[v]) updates.chemPercent=CHEMICAL_PRESETS[v]+"%";
    }
    if(f==="direction"){
      if(v==="Receive \u2192 Launch") updates.tank="Shuttle";
      else if(activeRun.tank==="Shuttle") updates.tank=proj.defaultTank||"Tank 1";
    }
    updateActiveRun(updates);
  };

  // updE — same field-update logic but for editingRun (past run being edited)
  const updE=(f,v)=>setER(prev=>{
    if(!prev) return prev;
    const n={...prev,[f]:v};
    if(f==="chemVolume")n.estVolumeOut=v;
    if(f==="chemType"){
      if(v==="HCL") n.chemPercent="18.0%";
      else if(v==="H2O"||v==="Det"||v==="Solvent"||v==="Diesel"||v==="Inhib. H2O") n.chemPercent="100%";
      else if(CHEMICAL_PRESETS[v]) n.chemPercent=CHEMICAL_PRESETS[v]+"%";
    }
    if(f==="direction"){if(v==="Receive \u2192 Launch")n.tank="Shuttle";else if(prev.tank==="Shuttle")n.tank=proj.defaultTank||"Tank 1"}
    if(f==="launchTime"&&prev.receiveTime) n.duration=prev.receiveTime-v-(prev.pausedDuration||0);
    if(f==="receiveTime"&&prev.launchTime) n.duration=v-prev.launchTime-(prev.pausedDuration||0);
    return n;
  });

  const cancel=()=>{ if(onClearRun) onClearRun(); else setPaused(false); };
  const cancelEdit=()=>{if(onClearEditingRun)onClearEditingRun();};

  // Popups for activeRun form
  const [pigPopup,setPigPopup]=useState(null);
  const [pigManual,setPigManual]=useState(null);
  const [chemPopup,setChemPopup]=useState(null);
  const [chemManualPct,setChemManualPct]=useState("");
  const [receivePopup,setReceivePopup]=useState(null);
  const [solidsManual,setSolidsManual]=useState("");

  // Popups for editingRun (past run) form — separate state so they don't interfere
  const [ePigPopup,setEPigPopup]=useState(null);
  const [ePigManual,setEPigManual]=useState(null);
  const [eChemPopup,setEChemPopup]=useState(null);
  const [eChemManualPct,setEChemManualPct]=useState("");
  const [eReceivePopup,setEReceivePopup]=useState(null);
  const [eSolidsManual,setESolidsManual]=useState("");

  const isShuttle=activeRun?.shuttleMode;
  const shuttleComplete=activeRun?.shuttleComplete;
  const shuttlePasses=activeRun?.shuttlePasses||[];

  // Manual time setter for editingRun
  const setEMT=(field,ts)=>{
    if(!ts||!editingRun)return;
    const d=new Date(),[h,m,s]=ts.split(":").map(Number);
    d.setHours(h||0,m||0,s||0,0);
    const t=d.getTime();
    setER(prev=>{
      const n={...prev,[field]:t};
      if(field==="launchTime"&&prev.receiveTime)n.duration=prev.receiveTime-t-(prev.pausedDuration||0);
      if(field==="receiveTime"&&prev.launchTime)n.duration=t-prev.launchTime-(prev.pausedDuration||0);
      return n;
    });
  };

  return (
    <>
    <div style={{padding:"12px 16px",maxWidth:CONTAINER_MAX,margin:"0 auto",paddingBottom:80}}>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:12}}>
        <div>
          <div style={{fontSize:18,fontWeight:900,fontFamily:"var(--display)"}}>IPS-PROJECT</div>
          <div style={{fontSize:10,color:"var(--muted)"}}>{proj.client} — {proj.diameter}" × {Number(proj.length||0).toLocaleString()}ft</div>
          {proj.jobNumber&&<div style={{fontSize:9,color:"var(--dim)"}}>Job #: {proj.jobNumber}</div>}
        </div>
        <div style={{fontSize:11,color:"var(--muted)"}}>{Fmt.date()}</div>
      </div>

      {showPrompt&&!activeRun&&<div style={{...S.card,textAlign:"center",padding:24}}>
        <div style={{fontSize:15,fontWeight:700,marginBottom:16}}>Run #{runs.length+1}</div>
        <div style={{display:"flex",gap:12}}>
          {runs.length>0&&<button style={{...S.ba,flex:1,padding:"16px 12px",fontSize:15}} onClick={()=>onStartNew(true)}>↻ Same as Last</button>}
          <button style={{...S.bp,flex:1,padding:"16px 12px",fontSize:15}} onClick={()=>onStartNew(false)}>+ New Run</button>
        </div>
      </div>}

      {activeRun&&<div>
        <div style={{...S.card,textAlign:"center",padding:16}}>
          <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:8}}>
            <span style={{fontSize:13,fontWeight:800,color:"var(--accent)"}}>RUN #{activeRun.runNumber}{isShuttle?" 🔄 SHUTTLE":""}</span>
            <input type="number" value={activeRun.runNumber} onChange={e=>updA("runNumber",parseInt(e.target.value)||1)} style={{...S.inp,width:60,textAlign:"center",padding:"4px 8px",fontSize:13}} />
          </div>

          {isShuttle&&shuttlePasses.length>0&&<div style={{background:"rgba(255,165,0,0.06)",borderRadius:10,padding:10,marginBottom:10,textAlign:"left"}}>
            <div style={{fontSize:10,color:"var(--accent)",fontWeight:800,textTransform:"uppercase",marginBottom:6}}>Shuttle Passes</div>
            {shuttlePasses.map((p,i)=>(
              <div key={i} style={{fontSize:11,color:"var(--muted)",marginBottom:3,display:"flex",justifyContent:"space-between"}}>
                <span>Pass {i+1}: {p.direction&&p.direction.startsWith("Launch")?"L→R":"R→L"}</span>
                <span style={{color:"var(--text)"}}>{Fmt.duration(p.duration)} · {p.contactTime}</span>
              </div>
            ))}
          </div>}

          <div style={{fontSize:10,color:"var(--muted)",textTransform:"uppercase"}}>{isShuttle&&shuttlePasses.length>0?`Pass ${shuttlePasses.length+1} Time`:"Run Time"}</div>
          <div style={{fontSize:44,fontWeight:900,fontFamily:"var(--mono)",color:paused?"#ffab00":activeRun.launchTime&&!activeRun.receiveTime?"#00e676":"var(--text)",margin:"4px 0"}}>{activeRun.launchTime&&!activeRun.receiveTime?Fmt.timer(elapsed):activeRun.duration?Fmt.duration(activeRun.duration):"00:00:00"}</div>
          {paused&&<div style={{fontSize:12,fontWeight:700,color:"#ffab00",marginBottom:4}}>⏸ PAUSED</div>}
          <div style={{display:"flex",gap:6,justifyContent:"center",fontSize:11,color:"var(--muted)",marginBottom:8}}>
            <span>Launch: {Fmt.time(activeRun.launchTime)}</span><span>|</span>
            <span>Rcv: {activeRun._shuttleReceiveTime?Fmt.time(activeRun._shuttleReceiveTime):Fmt.time(activeRun.receiveTime)}</span>
          </div>

          {shuttleComplete&&<div style={{background:"rgba(0,230,118,0.06)",borderRadius:10,padding:8,marginBottom:10,fontSize:12,color:"#00e676",fontWeight:700}}>✓ Shuttle Complete — {shuttlePasses.length} passes</div>}

          <div style={{display:"flex",gap:8,justifyContent:"center",flexWrap:"wrap"}}>
            {!activeRun.launchTime&&!shuttleComplete&&<>
              <button onClick={hLaunch} style={{...S.bp,background:"#00c853",boxShadow:"0 4px 20px rgba(0,200,83,0.3)",flex:1,fontSize:16,padding:14}}>▶ LAUNCH</button>
              {!isShuttle&&<button onClick={()=>updA("shuttleMode",true)} style={{...S.ba,padding:"14px 16px",width:"auto",fontSize:13,borderRadius:12}}>🔄 Shuttle</button>}
              {isShuttle&&shuttlePasses.length>0&&<button onClick={hEndShuttleBetweenPasses} style={{...S.bp,background:"linear-gradient(135deg,#7c4dff,#b039f5)",flex:1,fontSize:14,padding:14}}>⬛ End Shuttle</button>}
            </>}
            {activeRun.launchTime&&!shuttleComplete&&<>
              <button onClick={hPause} style={{...S.bs,flex:0.5,padding:14,background:paused?"rgba(0,230,118,0.12)":"rgba(255,171,0,0.12)",color:paused?"#00e676":"#ffab00",border:`1px solid ${paused?"rgba(0,230,118,0.3)":"rgba(255,171,0,0.3)"}`}}>{paused?"▶ Resume":"⏸ Pause"}</button>
              <button onClick={hReceive} style={{...S.bp,background:"#ff1744",boxShadow:"0 4px 20px rgba(255,23,68,0.3)",flex:1,fontSize:16,padding:14}}>■ RECEIVE</button>
              {isShuttle&&<button onClick={hEndShuttle} style={{...S.bp,background:"linear-gradient(135deg,#7c4dff,#b039f5)",flex:1,fontSize:14,padding:14}}>⬛ End Shuttle</button>}
            </>}
            {shuttleComplete&&<div style={{fontSize:14,fontWeight:700,color:"#00e676",padding:"12px 0"}}>✓ Shuttle Complete</div>}
            {activeRun.receiveTime&&!isShuttle&&!activeRun.launchTime&&<div style={{fontSize:14,fontWeight:700,color:"#00e676",padding:"12px 0"}}>✓ Run Complete</div>}
          </div>

          <div style={{display:"flex",gap:8,marginTop:12}}>
            <div style={{flex:1}}><label style={{...S.lb,fontSize:9}}>Manual Launch</label><input type="time" step="1" style={{...S.inp,fontSize:12,padding:"6px 8px",textAlign:"center"}} onChange={e=>setMT("launchTime",e.target.value)} /></div>
            <div style={{flex:1}}><label style={{...S.lb,fontSize:9}}>Manual Receive</label><input type="time" step="1" style={{...S.inp,fontSize:12,padding:"6px 8px",textAlign:"center"}} onChange={e=>setMT("receiveTime",e.target.value)} /></div>
          </div>
        </div>

        <div style={{...S.card,padding:"12px 16px"}}><QuickPick label="Direction" options={DIRECTION_OPTIONS} value={activeRun.direction} onChange={v=>updA("direction",v)} /></div>

        <div style={S.card}><div style={S.ct}>Pigs</div>
          <div style={{display:"flex",gap:8,flexWrap:"wrap"}}>
            {[["Front Pig","frontPig"],["Rear Pig","rearPig"],activeRun.showThirdPig&&["Third Pig","thirdPig"]].filter(Boolean).map(([lbl,field])=>(
              <div key={field} style={{flex:1,minWidth:90}}>
                <label style={S.lb}>{lbl}</label>
                <button onClick={()=>setPigPopup(field)} style={{...S.ba,width:"100%",padding:"10px 8px",fontSize:13,textAlign:"center"}}>
                  {activeRun[field]||"Select"}
                </button>
              </div>
            ))}
          </div>
          {!activeRun.showThirdPig&&<button onClick={()=>updA("showThirdPig",true)} style={{background:"none",border:"1px dashed var(--border)",borderRadius:8,color:"var(--muted)",fontSize:11,padding:"6px 12px",cursor:"pointer",marginTop:10,width:"100%",fontFamily:"var(--font)"}}>+ Third Pig</button>}
          {pigPopup&&<PopupMenu title={pigPopup==="frontPig"?"Front Pig":pigPopup==="rearPig"?"Rear Pig":"Third Pig"} options={[...PIG_OPTIONS,"Manual"]} onSelect={v=>{if(v==="Manual"){setPigManual({field:pigPopup,val:""});setPigPopup(null)}else{updA(pigPopup,v);setPigPopup(null)}}} onClose={()=>setPigPopup(null)} />}
          {pigManual&&<PopupMenu title="Manual Pig Entry" options={[]} onSelect={()=>{}} onClose={()=>setPigManual(null)} showManual manualLabel="Pig Name" manualValue={pigManual.val} onManualChange={v=>setPigManual(p=>({...p,val:v}))} onManualConfirm={()=>{updA(pigManual.field,pigManual.val);setPigManual(null)}} />}
        </div>

        <div style={S.card}><div style={S.ct}>Chemical</div>
          <div style={{display:"flex",gap:8,marginBottom:12,flexWrap:"wrap"}}>
            <div style={{flex:1,minWidth:90}}>
              <label style={S.lb}>Type</label>
              <button onClick={()=>setChemPopup("type")} style={{...S.ba,width:"100%",padding:"10px 8px",fontSize:13}}>
                {activeRun.chemType==="Other"?(activeRun.chemManualType||"Other"):activeRun.chemType}
              </button>
            </div>
            {activeRun.chemType!=="H2O"&&<div style={{flex:1,minWidth:90}}>
              <label style={S.lb}>{activeRun.chemType==="HCL"?"HCL Conc.":"% Loaded"}</label>
              <button onClick={()=>setChemPopup("percent")} style={{...S.ba,width:"100%",padding:"10px 8px",fontSize:13}}>
                {activeRun.chemPercent||"—"}
              </button>
            </div>}
            <div style={{flex:1,minWidth:90}}>
              <label style={S.lb}>Volume (gal)</label>
              <input type="number" inputMode="decimal" value={activeRun.chemVolume} onChange={e=>updA("chemVolume",e.target.value)} style={{...S.inp,textAlign:"center"}} placeholder="Enter gallons..." />
            </div>
          </div>
          {activeRun.chemType==="Other"&&<input placeholder="Specify chemical..." value={activeRun.chemManualType} onChange={e=>updA("chemManualType",e.target.value)} style={{...S.inp,marginTop:8}} />}
          {chemPopup==="type"&&<PopupMenu title="Chemical Type" options={CHEMICAL_TYPES} onSelect={v=>{updA("chemType",v);setChemPopup(null)}} onClose={()=>setChemPopup(null)} />}
          {chemPopup==="percent"&&activeRun.chemType==="HCL"&&<PopupMenu title="HCL Concentration" options={["10.0%","12.0%","13.0%","14.0%","15.0%","16.0%","17.0%","18.0%","19.0%","20.0%","21.0%","22.0%","Manual"]} onSelect={v=>{if(v==="Manual"){setChemManualPct("");setChemPopup("pctManual")}else{updA("chemPercent",v);setChemPopup(null)}}} onClose={()=>setChemPopup(null)} />}
          {chemPopup==="percent"&&activeRun.chemType!=="HCL"&&<PopupMenu title="% Loaded" options={["12%","13%","14%","15%","16%","17%","18%","19%","20%","21%","22%","23%","Manual"]} onSelect={v=>{if(v==="Manual"){setChemManualPct("");setChemPopup("pctManual")}else{updA("chemPercent",v);setChemPopup(null)}}} onClose={()=>setChemPopup(null)} />}
          {chemPopup==="pctManual"&&<PopupMenu title="Manual % Entry" options={[]} onSelect={()=>{}} onClose={()=>setChemPopup(null)} showManual manualLabel="Enter %" manualValue={chemManualPct} onManualChange={setChemManualPct} onManualConfirm={()=>{updA("chemPercent",chemManualPct.includes("%")?chemManualPct:chemManualPct+"%");setChemPopup(null)}} />}
        </div>

        <div style={S.card}><div style={S.ct}>Receive Data</div>
          <div style={{display:"flex",gap:12,marginBottom:12}}>
            <div style={{flex:1}}><label style={S.lb}>Est. Volume Out (gal)</label><input type="number" value={activeRun.estVolumeOut} onChange={e=>updA("estVolumeOut",e.target.value)} style={S.inp} /></div>
            <div style={{flex:1}}><QuickPick label="Tank #" options={TANK_OPTIONS} value={activeRun.tank} onChange={v=>updA("tank",v)} /></div>
          </div>

          {/* Current in-progress shuttle pass receive data */}
          {isShuttle&&!shuttleComplete&&activeRun.launchTime&&<div style={{background:"rgba(255,23,68,0.04)",border:"1px solid rgba(255,23,68,0.2)",borderRadius:10,padding:"10px 12px",marginBottom:12}}>
            <div style={{fontSize:10,color:"#ff6b6b",fontWeight:800,textTransform:"uppercase",marginBottom:8}}>Current Pass {(activeRun.shuttlePasses||[]).length+1} — Receive Data</div>
            <div style={{display:"flex",gap:8,marginBottom:4}}>
              <div style={{flex:1}}>
                <label style={S.lb}>% Solids</label>
                <button onClick={()=>setReceivePopup("passSolids")} style={{...S.ba,width:"100%",padding:"10px 8px",fontSize:14}}>{activeRun._passSolids||"NA"}</button>
              </div>
              <div style={{flex:1}}>
                <label style={S.lb}>% Acid</label>
                <input value={activeRun._passAcid||""} onChange={e=>updA("_passAcid",e.target.value)} placeholder="e.g. 2.5" style={{...S.inp,fontSize:14,textAlign:"center"}} inputMode="decimal" />
              </div>
              <div style={{flex:1}}>
                <label style={S.lb}>Color</label>
                <button onClick={()=>setReceivePopup("passColor")} style={{...S.ba,width:"100%",padding:"10px 8px",fontSize:14}}>{activeRun._passColor||"NA"}</button>
              </div>
            </div>
            {receivePopup==="passSolids"&&<PopupMenu title="% Solids" options={["Trace","<1","1.5","2","2.5","3","3.5","4","5","Manual"]} onSelect={v=>{if(v==="Manual"){setSolidsManual("");setReceivePopup("passSolidsManual")}else{updA("_passSolids",v);setReceivePopup(null)}}} onClose={()=>setReceivePopup(null)} />}
            {receivePopup==="passSolidsManual"&&<PopupMenu title="Manual Solids Entry" options={[]} onSelect={()=>{}} onClose={()=>setReceivePopup(null)} showManual manualLabel="Enter %" manualValue={solidsManual} onManualChange={setSolidsManual} onManualConfirm={()=>{updA("_passSolids",solidsManual);setReceivePopup(null)}} />}
            {receivePopup==="passColor"&&<PopupMenu title="Solid Color" options={SOLID_COLORS} onSelect={v=>{updA("_passColor",v);setReceivePopup(null)}} onClose={()=>setReceivePopup(null)} />}
          </div>}

          {/* Per-pass solids/acid/color for shuttle mode — editable inline during active run */}
          {isShuttle&&(activeRun.shuttlePasses||[]).length>0&&<InlinePassEditor passes={activeRun.shuttlePasses} onUpdatePass={(pi,updates)=>{const updated=(activeRun.shuttlePasses||[]).map((p,i)=>i===pi?{...p,...updates}:p);updateActiveRun({shuttlePasses:updated});}} />}

          {/* Non-shuttle solids/acid/color */}
          {!isShuttle&&<div style={{display:"flex",gap:8,marginBottom:12,flexWrap:"wrap"}}>
            <div style={{flex:1,minWidth:90}}>
              <label style={S.lb}>Total % Solids</label>
              <button onClick={()=>setReceivePopup("solids")} style={{...S.ba,width:"100%",padding:"10px 8px",fontSize:13}}>{activeRun.totalSolids||"0"}</button>
            </div>
            <div style={{flex:1,minWidth:90}}>
              <label style={S.lb}>% Acid (Receiving)</label>
              <input value={activeRun.percentAcid||""} onChange={e=>updA("percentAcid",e.target.value)} placeholder="e.g. 2.5" style={{...S.inp,fontSize:14,textAlign:"center"}} inputMode="decimal" />
            </div>
            <div style={{flex:1,minWidth:90}}>
              <label style={S.lb}>Solid Color</label>
              <button onClick={()=>setReceivePopup("color")} style={{...S.ba,width:"100%",padding:"10px 8px",fontSize:13}}>{activeRun.solidColor||"Black"}</button>
            </div>
          </div>}
          {receivePopup==="solids"&&<PopupMenu title="Total % Solids" options={["Trace","<1","1.5","2","2.5","3","3.5","4","5","Manual"]} onSelect={v=>{if(v==="Manual"){setSolidsManual("");setReceivePopup("solidsManual")}else{updA("totalSolids",v);setReceivePopup(null)}}} onClose={()=>setReceivePopup(null)} />}
          {receivePopup==="solidsManual"&&<PopupMenu title="Manual Solids Entry" options={[]} onSelect={()=>{}} onClose={()=>setReceivePopup(null)} showManual manualLabel="Enter %" manualValue={solidsManual} onManualChange={setSolidsManual} onManualConfirm={()=>{updA("totalSolids",solidsManual);setReceivePopup(null)}} />}
          {receivePopup==="color"&&<PopupMenu title="Solid Color" options={SOLID_COLORS} onSelect={v=>{updA("solidColor",v);setReceivePopup(null)}} onClose={()=>setReceivePopup(null)} />}
          {!isShuttle&&<><button onClick={()=>updA("layeredEnabled",!activeRun.layeredEnabled)} style={{background:activeRun.layeredEnabled?"var(--highlight)":"none",border:"1px dashed var(--border)",borderRadius:8,color:activeRun.layeredEnabled?"var(--accent)":"var(--muted)",fontSize:11,padding:"6px 12px",cursor:"pointer",width:"100%",fontFamily:"var(--font)"}}>{activeRun.layeredEnabled?"▾ Layered Solids":"+ Layered Solids"}</button>
          {activeRun.layeredEnabled&&<div style={{marginTop:10,display:"flex",flexDirection:"column",gap:8}}>
            {[["Top","layeredTop","layeredTopColor"],["Middle","layeredMid","layeredMidColor"],["Bottom","layeredBot","layeredBotColor"]].map(([lbl,pctField,colorField])=>(
              <div key={lbl} style={{display:"flex",gap:6,alignItems:"flex-end"}}>
                <div style={{flex:1}}><label style={S.lb}>{lbl} %</label><ScrollPicker label="" options={PERCENT_FINE} value={activeRun[pctField]} onChange={v=>updA(pctField,v)} width={90} fontSize={12} /></div>
                <div style={{flex:1}}>
                  <label style={S.lb}>{lbl} Color</label>
                  <select value={activeRun[colorField]||""} onChange={e=>updA(colorField,e.target.value)} style={{...S.inp,fontSize:12,padding:"8px 10px"}}>
                    <option value="">— Color —</option>
                    {SOLID_COLORS.map(c=><option key={c} value={c}>{c}</option>)}
                  </select>
                </div>
              </div>
            ))}
          </div>}</>}
        </div>

        <div style={S.card}><div style={S.ct}>Run Notes</div><textarea rows={2} placeholder="Notes for this run..." value={activeRun.notes} onChange={e=>updA("notes",e.target.value)} style={{...S.inp,resize:"vertical",minHeight:50}} /></div>

        <div style={{position:"sticky",bottom:56,background:"linear-gradient(to top, var(--bg) 60%, transparent)",padding:"12px 0",zIndex:50}}>
          <div style={{display:"flex",gap:10}}>
            <button onClick={cancel} style={{...S.bs,flex:0.4,padding:14}}>Cancel</button>
            {false&&<button onClick={onSaveRun} style={{...S.bp,flex:1,padding:14,fontSize:15}}>✓ Save Run #{activeRun.runNumber}</button>}
          </div>
        </div>
      </div>}

      {runs.filter(r=>r.receiveTime||r.shuttleComplete||r._saved).length>0&&<div style={{marginTop:16}}>
        <div style={{fontSize:11,color:"var(--muted)",fontWeight:700,textTransform:"uppercase",marginBottom:8}}>Saved Runs ({runs.filter(r=>r.receiveTime||r.shuttleComplete||r._saved).length}) · swipe left to delete</div>
        {[...runs].reverse().filter(r=>r.receiveTime||r.shuttleComplete||r._saved).map((r,i)=>{
          const actualIdx = runs.findIndex(x=>x.id===r.id);
          const isEditingThisRun = editPassRun && editPassRun.runIdx === actualIdx;
          return (
            <div key={r.id}>
              <SwipeRow onDelete={()=>{if(isEditingThisRun)setEditPassRun(null);onDeleteRun(actualIdx)}}>
                <div style={{...S.card,padding:"10px 14px",marginBottom:0,display:"flex",justifyContent:"space-between",alignItems:"center",borderRadius:14}}>
                  <div onClick={()=>{setER({...runs[actualIdx]});}} style={{flex:1,cursor:"pointer"}}>
                    <span style={{fontWeight:800,color:"var(--accent)",fontSize:13}}>#{r.runNumber}</span>
                    {r.shuttleMode&&<span style={{fontSize:10,color:"#ffab00",marginLeft:6}}>🔄 Shuttle</span>}
                    {r.shuttleMode&&(r.shuttlePasses||[]).map((sp,spi)=>(
                      <span key={spi} style={{display:"inline-flex",alignItems:"center",gap:3,fontSize:9,marginLeft:6,background:"rgba(255,171,0,0.08)",border:"1px solid rgba(255,171,0,0.25)",borderRadius:4,padding:"1px 5px",color:sp.launchTime&&sp.receiveTime?"#ffab00":"#ff6b6b"}}>
                        P{spi+1}: {sp.launchTime?Fmt.timeShort(sp.launchTime):<span style={{color:"#ff6b6b"}}>—</span>}→{sp.receiveTime?Fmt.timeShort(sp.receiveTime):<span style={{color:"#ff6b6b"}}>—</span>}
                      </span>
                    ))}
                    {(()=>{
                      if(r.shuttleMode){
                        if(r.shuttleComplete) return null;
                        const spasses=r.shuttlePasses||[];
                        const hasInFlight=!!r.launchTime; // active pass mid-run (launchTime set on run = pass in progress)
                        const label=hasInFlight?"▶ Live":spasses.length>0?"▶ Live":"⏳ Staged";
                        return <span style={{fontSize:9,fontWeight:900,color:"#00e676",background:"rgba(0,230,118,0.1)",border:"1px solid rgba(0,230,118,0.3)",borderRadius:5,padding:"1px 6px",marginLeft:6,textTransform:"uppercase",letterSpacing:"0.08em"}}>{label}</span>;
                      } else {
                        if(r.receiveTime) return null;
                        return <span style={{fontSize:9,fontWeight:900,color:"#00e676",background:"rgba(0,230,118,0.1)",border:"1px solid rgba(0,230,118,0.3)",borderRadius:5,padding:"1px 6px",marginLeft:6,textTransform:"uppercase",letterSpacing:"0.08em"}}>{r.launchTime?"▶ Live":"⏳ Staged"}</span>;
                      }
                    })()}
                    <span style={{color:"var(--muted)",fontSize:12,marginLeft:8}}>{r.frontPig}{r.rearPig!=="None"?"/"+r.rearPig:""}</span>
                    <span style={{color:"var(--dim)",fontSize:12,marginLeft:8}}>{r.chemVolume}g {r.chemType}</span>
                    <div style={{fontSize:10,color:"var(--dim)",marginTop:2}}>{r.direction&&r.direction.startsWith("Launch")?"L→R":"R→L"}</div>
                  </div>
                  <div style={{display:"flex",alignItems:"center",gap:8,flexWrap:"wrap",justifyContent:"flex-end"}}>
                    <div style={{textAlign:"right",fontSize:12,color:"var(--muted)"}}>{Fmt.duration(r.duration)}</div>
                    {r.shuttleMode&&!r.shuttleComplete&&<button onClick={e=>{e.stopPropagation();const passes=r.shuttlePasses||[];const totalDur=passes.reduce((s,p)=>s+(p.duration||0),0);const lastReceiveTime=r._shuttleReceiveTime||r.receiveTime||Date.now();const firstPassDir=passes[0]?.direction||r.direction;setRuns(prev=>prev.map(x=>x.id===r.id?{...x,receiveTime:lastReceiveTime,duration:totalDur,shuttleComplete:true,launchTime:null,direction:firstPassDir,_saved:false}:x));}} style={{background:"linear-gradient(135deg,#7c4dff,#b039f5)",border:"none",borderRadius:8,color:"#fff",fontSize:11,fontWeight:800,padding:"6px 10px",cursor:"pointer",fontFamily:"var(--font)",whiteSpace:"nowrap"}}>⬛ End Shuttle</button>}
                    {r.shuttlePasses&&r.shuttlePasses.length>0&&<button onClick={e=>{e.stopPropagation();if(isEditingThisRun){setEditPassRun(null)}else{setEditPassRun({runIdx:actualIdx,passIdx:0});setEditPassData({...(r.shuttlePasses[0]||{})});setPassPopup(null);}}} style={{background:isEditingThisRun?"rgba(255,171,0,0.2)":"rgba(255,171,0,0.08)",border:"1px solid rgba(255,171,0,0.35)",borderRadius:8,color:"#ffab00",fontSize:11,fontWeight:700,padding:"6px 10px",cursor:"pointer",fontFamily:"var(--font)",whiteSpace:"nowrap"}}>{isEditingThisRun?"✕ Close":"✎ Passes"}</button>}
                    <button onClick={e=>{e.stopPropagation();onDuplicateRun(actualIdx)}} style={{background:"rgba(255,165,0,0.12)",border:"1px solid rgba(255,165,0,0.3)",borderRadius:8,color:"var(--accent)",fontSize:11,fontWeight:700,padding:"6px 10px",cursor:"pointer",fontFamily:"var(--font)",whiteSpace:"nowrap"}}>⎘ Dup</button>
                  </div>
                </div>
              </SwipeRow>
              {isEditingThisRun&&<div style={{background:"rgba(255,171,0,0.04)",border:"1px solid rgba(255,171,0,0.2)",borderRadius:12,padding:"12px 14px",marginBottom:8,marginTop:-4}}>
                <div style={{fontSize:11,color:"var(--accent)",fontWeight:800,textTransform:"uppercase",marginBottom:10}}>Edit Pass Data — Run #{r.runNumber}</div>
                <div style={{display:"flex",gap:6,marginBottom:12,flexWrap:"wrap"}}>
                  {(r.shuttlePasses||[]).map((p,pi)=>(
                    <button key={pi} onClick={()=>{setEditPassRun({runIdx:actualIdx,passIdx:pi});setEditPassData({...(r.shuttlePasses[pi]||{})});setPassPopup(null);}} style={{background:editPassRun.passIdx===pi?"var(--accent)":"rgba(255,171,0,0.1)",border:"1px solid rgba(255,171,0,0.3)",borderRadius:8,color:editPassRun.passIdx===pi?"#000":"var(--accent)",fontSize:12,fontWeight:700,padding:"6px 12px",cursor:"pointer",fontFamily:"var(--font)"}}>Pass {pi+1}</button>
                  ))}
                </div>
                {(()=>{
                  const pi = editPassRun.passIdx;
                  const p = r.shuttlePasses[pi];
                  return <div>
                    <div style={{fontSize:11,color:"var(--muted)",marginBottom:8}}>{dirLabel(p.direction)} · {p.launchTime?Fmt.timeShort(p.launchTime):<span style={{color:"#ff6b6b"}}>No launch</span>} → {p.receiveTime?Fmt.timeShort(p.receiveTime):<span style={{color:"#ff6b6b"}}>No receive</span>} · {Fmt.duration(p.duration)}</div>
                    <div style={{display:"flex",gap:6,marginBottom:10}}>
                      <div style={{flex:1}}>
                        <label style={S.lb}>Launch Time</label>
                        <input type="time" step="1" defaultValue={editPassData.launchTime?new Date(editPassData.launchTime).toTimeString().slice(0,8):""} onChange={e=>{const[h,m,s]=e.target.value.split(":").map(Number);const d=new Date(editPassData.launchTime||Date.now());d.setHours(h,m,s||0,0);const t=d.getTime();setEditPassData(d=>({...d,launchTime:t,duration:d.receiveTime?d.receiveTime-t-(d.pausedDuration||0):d.duration}));}} style={{...S.inp,fontSize:12,padding:"6px 8px",textAlign:"center"}} />
                      </div>
                      <div style={{flex:1}}>
                        <label style={S.lb}>Receive Time</label>
                        <input type="time" step="1" defaultValue={editPassData.receiveTime?new Date(editPassData.receiveTime).toTimeString().slice(0,8):""} onChange={e=>{const[h,m,s]=e.target.value.split(":").map(Number);const d=new Date(editPassData.receiveTime||Date.now());d.setHours(h,m,s||0,0);const t=d.getTime();setEditPassData(d=>({...d,receiveTime:t,duration:d.launchTime?t-d.launchTime-(d.pausedDuration||0):d.duration}));}} style={{...S.inp,fontSize:12,padding:"6px 8px",textAlign:"center"}} />
                      </div>
                    </div>
                    <div style={{display:"flex",gap:8,marginBottom:10}}>
                      <div style={{flex:1}}>
                        <label style={S.lb}>% Solids</label>
                        <button onClick={()=>setPassPopup("solids")} style={{...S.ba,width:"100%",padding:"10px 8px",fontSize:14}}>{editPassData.totalSolids||"NA"}</button>
                      </div>
                      <div style={{flex:1}}>
                        <label style={S.lb}>% Acid</label>
                        <input value={editPassData.percentAcid||""} onChange={e=>setEditPassData(d=>({...d,percentAcid:e.target.value}))} placeholder="e.g. 2.5" style={{...S.inp,fontSize:14,textAlign:"center"}} inputMode="decimal" />
                      </div>
                      <div style={{flex:1}}>
                        <label style={S.lb}>Color</label>
                        <button onClick={()=>setPassPopup("color")} style={{...S.ba,width:"100%",padding:"10px 8px",fontSize:14}}>{editPassData.solidColor||"NA"}</button>
                      </div>
                    </div>
                    {passPopup==="solids"&&<PopupMenu title="% Solids" options={["Trace","<1","1.5","2","2.5","3","3.5","4","5","Manual"]} onSelect={v=>{if(v==="Manual"){setPassManual("");setPassPopup("solidsManual")}else{setEditPassData(d=>({...d,totalSolids:v}));setPassPopup(null)}}} onClose={()=>setPassPopup(null)} />}
                    {passPopup==="solidsManual"&&<PopupMenu title="Manual Solids" options={[]} onSelect={()=>{}} onClose={()=>setPassPopup(null)} showManual manualLabel="Enter %" manualValue={passManual} onManualChange={setPassManual} onManualConfirm={()=>{setEditPassData(d=>({...d,totalSolids:passManual}));setPassPopup(null)}} />}
                    {passPopup==="color"&&<PopupMenu title="Solid Color" options={SOLID_COLORS} onSelect={v=>{setEditPassData(d=>({...d,solidColor:v}));setPassPopup(null)}} onClose={()=>setPassPopup(null)} />}
                    <button onClick={()=>{
                      const updated = runs[actualIdx].shuttlePasses.map((p,idx)=>idx===pi?{...p,...editPassData}:p);
                      const updatedRun = {...runs[actualIdx],shuttlePasses:updated};
                      setER(updatedRun);
                      setTimeout(()=>{onSavePastRun();setEditPassRun(null);},50);
                    }} style={{...S.bp,width:"100%",padding:12,fontSize:14}}>✓ Save Pass {pi+1} Data</button>
                  </div>;
                })()}
              </div>}
            </div>
          );
        })}
      </div>}
    </div>

    {/* ══ EDIT PAST RUN MODAL OVERLAY ══
        Full-screen slide-up panel — appears over the runs list while activeRun may still be timing.
        Uses editingRun state + updE() so the live timer is completely untouched. */}
    {editingRun&&<div style={{position:"fixed",inset:0,zIndex:300,background:"rgba(0,0,0,0.7)",display:"flex",flexDirection:"column",justifyContent:"flex-end"}}>
      <div style={{background:"var(--bg)",borderRadius:"20px 20px 0 0",border:"1px solid var(--border)",maxHeight:"92vh",overflowY:"auto",paddingBottom:"calc(80px + env(safe-area-inset-bottom,0))"}}>

        {/* Header */}
        <div style={{position:"sticky",top:0,background:"var(--bg)",zIndex:10,borderBottom:"1px solid var(--border)",padding:"14px 16px 10px"}}>
          <div style={{width:36,height:4,background:"var(--border)",borderRadius:2,margin:"0 auto 10px"}} />
          <div style={{display:"flex",justifyContent:"space-between",alignItems:"center"}}>
            <div>
              <div style={{fontSize:15,fontWeight:900,color:"var(--accent)"}}>Edit Run #{editingRun.runNumber}</div>
              <div style={{fontSize:10,color:"var(--muted)"}}>Changes save to history · timer unaffected</div>
            </div>
            <button onClick={cancelEdit} style={{background:"rgba(0,0,0,0.06)",border:"1px solid var(--border)",borderRadius:10,padding:"8px 14px",color:"var(--muted)",fontSize:13,fontWeight:700,cursor:"pointer",fontFamily:"var(--font)"}}>✕ Close</button>
          </div>
          {activeRun&&activeRun.launchTime&&!activeRun.receiveTime&&<div style={{marginTop:8,background:"rgba(0,200,83,0.08)",border:"1px solid rgba(0,200,83,0.25)",borderRadius:8,padding:"6px 10px",fontSize:11,color:"#00e676",fontWeight:700}}>
            ▶ Run #{activeRun.runNumber} is still timing — {Fmt.timer(elapsed)}
          </div>}
        </div>

        <div style={{padding:"12px 16px"}}>

          {/* Times */}
          <div style={{...S.card,padding:14}}>
            <div style={S.ct}>Times</div>
            <div style={{display:"flex",gap:8,marginBottom:8}}>
              <div style={{flex:1}}>
                <label style={S.lb}>Launch Time</label>
                <input type="time" step="1" defaultValue={editingRun.launchTime?new Date(editingRun.launchTime).toTimeString().slice(0,8):""} onChange={e=>setEMT("launchTime",e.target.value)} style={{...S.inp,fontSize:13,padding:"8px 10px",textAlign:"center"}} />
                <div style={{fontSize:9,color:"var(--dim)",marginTop:2,textAlign:"center"}}>{editingRun.launchTime?Fmt.time(editingRun.launchTime):"—"}</div>
              </div>
              <div style={{flex:1}}>
                <label style={S.lb}>Receive Time</label>
                <input type="time" step="1" defaultValue={editingRun.receiveTime?new Date(editingRun.receiveTime).toTimeString().slice(0,8):""} onChange={e=>setEMT("receiveTime",e.target.value)} style={{...S.inp,fontSize:13,padding:"8px 10px",textAlign:"center"}} />
                <div style={{fontSize:9,color:"var(--dim)",marginTop:2,textAlign:"center"}}>{editingRun.receiveTime?Fmt.time(editingRun.receiveTime):"—"}</div>
              </div>
            </div>
            {editingRun.duration>0&&<div style={{textAlign:"center",fontSize:12,color:"var(--accent)",fontWeight:800}}>Duration: {Fmt.duration(editingRun.duration)}</div>}
          </div>

          {/* Direction */}
          <div style={{...S.card,padding:"12px 16px"}}><QuickPick label="Direction" options={DIRECTION_OPTIONS} value={editingRun.direction} onChange={v=>updE("direction",v)} /></div>

          {/* Pigs */}
          <div style={S.card}><div style={S.ct}>Pigs</div>
            <div style={{display:"flex",gap:8,flexWrap:"wrap"}}>
              {[["Front Pig","frontPig"],["Rear Pig","rearPig"],editingRun.showThirdPig&&["Third Pig","thirdPig"]].filter(Boolean).map(([lbl,field])=>(
                <div key={field} style={{flex:1,minWidth:90}}>
                  <label style={S.lb}>{lbl}</label>
                  <button onClick={()=>setEPigPopup(field)} style={{...S.ba,width:"100%",padding:"10px 8px",fontSize:13}}>{editingRun[field]||"Select"}</button>
                </div>
              ))}
            </div>
            {!editingRun.showThirdPig&&<button onClick={()=>updE("showThirdPig",true)} style={{background:"none",border:"1px dashed var(--border)",borderRadius:8,color:"var(--muted)",fontSize:11,padding:"6px 12px",cursor:"pointer",marginTop:10,width:"100%",fontFamily:"var(--font)"}}>+ Third Pig</button>}
            {ePigPopup&&<PopupMenu title={ePigPopup==="frontPig"?"Front Pig":ePigPopup==="rearPig"?"Rear Pig":"Third Pig"} options={[...PIG_OPTIONS,"Manual"]} onSelect={v=>{if(v==="Manual"){setEPigManual({field:ePigPopup,val:""});setEPigPopup(null)}else{updE(ePigPopup,v);setEPigPopup(null)}}} onClose={()=>setEPigPopup(null)} />}
            {ePigManual&&<PopupMenu title="Manual Pig Entry" options={[]} onSelect={()=>{}} onClose={()=>setEPigManual(null)} showManual manualLabel="Pig Name" manualValue={ePigManual.val} onManualChange={v=>setEPigManual(p=>({...p,val:v}))} onManualConfirm={()=>{updE(ePigManual.field,ePigManual.val);setEPigManual(null)}} />}
          </div>

          {/* Chemical */}
          <div style={S.card}><div style={S.ct}>Chemical</div>
            <div style={{display:"flex",gap:8,marginBottom:12,flexWrap:"wrap"}}>
              <div style={{flex:1,minWidth:90}}>
                <label style={S.lb}>Type</label>
                <button onClick={()=>setEChemPopup("type")} style={{...S.ba,width:"100%",padding:"10px 8px",fontSize:13}}>
                  {editingRun.chemType==="Other"?(editingRun.chemManualType||"Other"):editingRun.chemType}
                </button>
              </div>
              {editingRun.chemType!=="H2O"&&<div style={{flex:1,minWidth:90}}>
                <label style={S.lb}>{editingRun.chemType==="HCL"?"HCL Conc.":"% Loaded"}</label>
                <button onClick={()=>setEChemPopup("percent")} style={{...S.ba,width:"100%",padding:"10px 8px",fontSize:13}}>{editingRun.chemPercent||"—"}</button>
              </div>}
              <div style={{flex:1,minWidth:90}}>
                <label style={S.lb}>Volume (gal)</label>
                <input type="number" inputMode="decimal" value={editingRun.chemVolume} onChange={e=>updE("chemVolume",e.target.value)} style={{...S.inp,textAlign:"center"}} />
              </div>
            </div>
            {editingRun.chemType==="Other"&&<input placeholder="Specify chemical..." value={editingRun.chemManualType||""} onChange={e=>updE("chemManualType",e.target.value)} style={{...S.inp,marginTop:8}} />}
            {eChemPopup==="type"&&<PopupMenu title="Chemical Type" options={CHEMICAL_TYPES} onSelect={v=>{updE("chemType",v);setEChemPopup(null)}} onClose={()=>setEChemPopup(null)} />}
            {eChemPopup==="percent"&&editingRun.chemType==="HCL"&&<PopupMenu title="HCL Concentration" options={["10.0%","12.0%","13.0%","14.0%","15.0%","16.0%","17.0%","18.0%","19.0%","20.0%","21.0%","22.0%","Manual"]} onSelect={v=>{if(v==="Manual"){setEChemManualPct("");setEChemPopup("pctManual")}else{updE("chemPercent",v);setEChemPopup(null)}}} onClose={()=>setEChemPopup(null)} />}
            {eChemPopup==="percent"&&editingRun.chemType!=="HCL"&&<PopupMenu title="% Loaded" options={["12%","13%","14%","15%","16%","17%","18%","19%","20%","21%","22%","23%","Manual"]} onSelect={v=>{if(v==="Manual"){setEChemManualPct("");setEChemPopup("pctManual")}else{updE("chemPercent",v);setEChemPopup(null)}}} onClose={()=>setEChemPopup(null)} />}
            {eChemPopup==="pctManual"&&<PopupMenu title="Manual % Entry" options={[]} onSelect={()=>{}} onClose={()=>setEChemPopup(null)} showManual manualLabel="Enter %" manualValue={eChemManualPct} onManualChange={setEChemManualPct} onManualConfirm={()=>{updE("chemPercent",eChemManualPct.includes("%")?eChemManualPct:eChemManualPct+"%");setEChemPopup(null)}} />}
          </div>

          {/* Receive Data */}
          <div style={S.card}><div style={S.ct}>Receive Data</div>
            <div style={{display:"flex",gap:12,marginBottom:12}}>
              <div style={{flex:1}}><label style={S.lb}>Est. Volume Out (gal)</label><input type="number" value={editingRun.estVolumeOut||""} onChange={e=>updE("estVolumeOut",e.target.value)} style={S.inp} /></div>
              <div style={{flex:1}}><QuickPick label="Tank #" options={TANK_OPTIONS} value={editingRun.tank} onChange={v=>updE("tank",v)} /></div>
            </div>
            {!editingRun.shuttleMode&&<div style={{display:"flex",gap:8,marginBottom:8,flexWrap:"wrap"}}>
              <div style={{flex:1,minWidth:90}}>
                <label style={S.lb}>Total % Solids</label>
                <button onClick={()=>setEReceivePopup("solids")} style={{...S.ba,width:"100%",padding:"10px 8px",fontSize:13}}>{editingRun.totalSolids||"0"}</button>
              </div>
              <div style={{flex:1,minWidth:90}}>
                <label style={S.lb}>% Acid</label>
                <input value={editingRun.percentAcid||""} onChange={e=>updE("percentAcid",e.target.value)} placeholder="e.g. 2.5" style={{...S.inp,fontSize:14,textAlign:"center"}} inputMode="decimal" />
              </div>
              <div style={{flex:1,minWidth:90}}>
                <label style={S.lb}>Solid Color</label>
                <button onClick={()=>setEReceivePopup("color")} style={{...S.ba,width:"100%",padding:"10px 8px",fontSize:13}}>{editingRun.solidColor||"Black"}</button>
              </div>
            </div>}
            {eReceivePopup==="solids"&&<PopupMenu title="Total % Solids" options={["Trace","<1","1.5","2","2.5","3","3.5","4","5","Manual"]} onSelect={v=>{if(v==="Manual"){setESolidsManual("");setEReceivePopup("solidsManual")}else{updE("totalSolids",v);setEReceivePopup(null)}}} onClose={()=>setEReceivePopup(null)} />}
            {eReceivePopup==="solidsManual"&&<PopupMenu title="Manual Solids Entry" options={[]} onSelect={()=>{}} onClose={()=>setEReceivePopup(null)} showManual manualLabel="Enter %" manualValue={eSolidsManual} onManualChange={setESolidsManual} onManualConfirm={()=>{updE("totalSolids",eSolidsManual);setEReceivePopup(null)}} />}
            {eReceivePopup==="color"&&<PopupMenu title="Solid Color" options={SOLID_COLORS} onSelect={v=>{updE("solidColor",v);setEReceivePopup(null)}} onClose={()=>setEReceivePopup(null)} />}
          </div>

          {/* Shuttle pass data for completed shuttle runs */}
          {editingRun.shuttleMode&&(editingRun.shuttlePasses||[]).length>0&&<div style={S.card}>
            <div style={S.ct}>Shuttle Passes</div>
            {editingRun.shuttlePasses.map((p,pi)=>(
              <div key={pi} style={{background:"rgba(255,165,0,0.04)",borderRadius:8,padding:"10px 12px",marginBottom:8}}>
                <div style={{fontSize:11,fontWeight:700,color:"var(--accent)",marginBottom:6}}>Pass {pi+1}: {dirLabel(p.direction)} · {p.launchTime?Fmt.timeShort(p.launchTime):<span style={{color:"#ff6b6b"}}>No launch</span>}→{p.receiveTime?Fmt.timeShort(p.receiveTime):<span style={{color:"#ff6b6b"}}>No receive</span>}</div>
                <div style={{display:"flex",gap:6,marginBottom:8}}>
                  <div style={{flex:1}}>
                    <label style={S.lb}>Launch Time</label>
                    <input type="time" step="1" defaultValue={p.launchTime?new Date(p.launchTime).toTimeString().slice(0,8):""} onChange={e=>{const[h,m,s]=e.target.value.split(":").map(Number);const nd=new Date(p.launchTime||Date.now());nd.setHours(h,m,s||0,0);const t=nd.getTime();const up=editingRun.shuttlePasses.map((sp,si)=>si===pi?{...sp,launchTime:t,duration:sp.receiveTime?sp.receiveTime-t-(sp.pausedDuration||0):sp.duration}:sp);updE("shuttlePasses",up);}} style={{...S.inp,fontSize:12,padding:"6px 8px",textAlign:"center"}} />
                  </div>
                  <div style={{flex:1}}>
                    <label style={S.lb}>Receive Time</label>
                    <input type="time" step="1" defaultValue={p.receiveTime?new Date(p.receiveTime).toTimeString().slice(0,8):""} onChange={e=>{const[h,m,s]=e.target.value.split(":").map(Number);const nd=new Date(p.receiveTime||Date.now());nd.setHours(h,m,s||0,0);const t=nd.getTime();const up=editingRun.shuttlePasses.map((sp,si)=>si===pi?{...sp,receiveTime:t,duration:sp.launchTime?t-sp.launchTime-(sp.pausedDuration||0):sp.duration}:sp);updE("shuttlePasses",up);}} style={{...S.inp,fontSize:12,padding:"6px 8px",textAlign:"center"}} />
                  </div>
                </div>
                <div style={{display:"flex",gap:8}}>
                  <div style={{flex:1}}>
                    <label style={S.lb}>% Solids</label>
                    <input value={p.totalSolids||""} onChange={e=>{const up=editingRun.shuttlePasses.map((sp,si)=>si===pi?{...sp,totalSolids:e.target.value}:sp);updE("shuttlePasses",up);}} style={{...S.inp,fontSize:13,textAlign:"center"}} placeholder="0" />
                  </div>
                  <div style={{flex:1}}>
                    <label style={S.lb}>% Acid</label>
                    <input value={p.percentAcid||""} onChange={e=>{const up=editingRun.shuttlePasses.map((sp,si)=>si===pi?{...sp,percentAcid:e.target.value}:sp);updE("shuttlePasses",up);}} style={{...S.inp,fontSize:13,textAlign:"center"}} placeholder="0" inputMode="decimal" />
                  </div>
                  <div style={{flex:1}}>
                    <label style={S.lb}>Color</label>
                    <select value={p.solidColor||"Black"} onChange={e=>{const up=editingRun.shuttlePasses.map((sp,si)=>si===pi?{...sp,solidColor:e.target.value}:sp);updE("shuttlePasses",up);}} style={{...S.inp,fontSize:12,padding:"8px 6px"}}>
                      {SOLID_COLORS.map(c=><option key={c} value={c}>{c}</option>)}
                    </select>
                  </div>
                </div>
              </div>
            ))}
          </div>}

          {/* Notes */}
          <div style={S.card}><div style={S.ct}>Run Notes</div><textarea rows={3} placeholder="Notes for this run..." value={editingRun.notes||""} onChange={e=>updE("notes",e.target.value)} style={{...S.inp,resize:"vertical",minHeight:60}} /></div>

          {/* Run Number */}
          <div style={{...S.card,display:"flex",alignItems:"center",gap:12,padding:"12px 16px"}}>
            <label style={{...S.lb,marginBottom:0,whiteSpace:"nowrap"}}>Run Number</label>
            <input type="number" value={editingRun.runNumber} onChange={e=>updE("runNumber",parseInt(e.target.value)||1)} style={{...S.inp,width:80,textAlign:"center"}} />
          </div>

          {/* Save / Cancel */}
          <div style={{display:"flex",gap:10,marginTop:4,marginBottom:8}}>
            <button onClick={cancelEdit} style={{...S.bs,flex:0.4,padding:14}}>Cancel</button>
            <button onClick={onSavePastRun} style={{...S.bp,flex:1,padding:14,fontSize:15}}>✓ Save Run #{editingRun.runNumber}</button>
          </div>

        </div>
      </div>
    </div>}
    </>
  );
}
// Helper for direction display - FIXED
function dirLabel(dir) {
  if(!dir) return "—";
  return dir.startsWith("Launch") ? "L→R" : "R→L";
}

function RunSheetPage({runs,proj,coatingDays,onEditRun,NavBar}) {
  return (
    <div style={{padding:"12px 8px",paddingBottom:80,overflow:"auto"}}>
      <div style={{fontSize:16,fontWeight:900,fontFamily:"var(--display)",textAlign:"center",padding:"8px 0 8px"}}>RUN SHEET</div>
      <button onClick={()=>ReportGen.printRunSheet(runs,proj)} style={{...S.bs,margin:"0 8px 12px",fontSize:12,padding:"8px 16px",width:"auto"}}>🖨 Print Run Sheet</button>
      <div style={{overflow:"auto",borderRadius:10,border:"1px solid var(--border)"}}>
        <table style={{borderCollapse:"collapse",fontSize:11,fontFamily:"var(--font)",minWidth:1100,width:"100%"}}>
          <thead><tr style={{background:"var(--highlight)"}}>
            {["#","Date","Dir","Front","Rear","3rd","Chem","%","Vol","Launch","Rec.","Dur.","VolOut","Tank","Solids","Acid","Color","Notes"].map(h=>(
              <th key={h} style={{padding:"8px 4px",color:"var(--muted)",fontWeight:700,textTransform:"uppercase",fontSize:8,borderBottom:"2px solid var(--accent)",textAlign:"left",whiteSpace:"nowrap"}}>{h}</th>
            ))}
          </tr></thead>
          <tbody>
            {runs.map((r,ri)=>{
              const rows=[];
              if(r.shuttlePasses&&r.shuttlePasses.length>0){
                r.shuttlePasses.forEach((p,pi)=>{
                  rows.push(
                    <tr key={r.id+"p"+pi} style={{borderBottom:"1px solid var(--border)",background:pi===0?"rgba(255,165,0,0.04)":"transparent",cursor:"pointer"}} onClick={()=>onEditRun(ri)}>
                      <td style={S.td}><strong style={{color:"var(--accent)"}}>{r.runNumber}.{pi+1}</strong></td>
                      <td style={S.td}>{Fmt.date(r.date)}</td>
                      <td style={S.td}>{dirLabel(p.direction)}</td>
                      <td style={S.td}>{r.frontPig}</td>
                      <td style={S.td}>{r.rearPig!=="None"?r.rearPig:"—"}</td>
                      <td style={S.td}>{r.thirdPig!=="None"?r.thirdPig:"—"}</td>
                      <td style={S.td}>{r.chemType==="Other"?r.chemManualType:r.chemType}</td>
                      <td style={S.td}>{r.chemPercent}</td>
                      <td style={S.td}>{pi===0?r.chemVolume+"g":"↻"}</td>
                      <td style={S.td}>{Fmt.timeShort(p.launchTime)}</td>
                      <td style={S.td}>{Fmt.timeShort(p.receiveTime)}</td>
                      <td style={S.td}>{Fmt.duration(p.duration)}</td>
                      <td style={S.td}>{r.estVolumeOut+"g"}</td>
                      <td style={S.td}>{r.tank}</td>
                      <td style={S.td}>{p.totalSolids||"—"}</td>
                      <td style={S.td}>{p.percentAcid||"—"}</td>
                      <td style={S.td}>{p.solidColor||"—"}</td>
                      <td style={{...S.td,maxWidth:80,overflow:"hidden",textOverflow:"ellipsis"}}>{pi===0?(r.notes||"—"):"—"}</td>
                    </tr>
                  );
                });
                rows.push(
                  <tr key={r.id+"ct"} style={{background:"rgba(255,171,0,0.04)"}}>
                    <td colSpan={18} style={{...S.td,fontSize:10,color:"var(--accent)",fontStyle:"italic",paddingLeft:12}}>
                      🔄 Shuttle Run — {r.shuttlePasses.length} passes · Contact per pass: {r.shuttlePasses.map((p,i)=>`Pass ${i+1}: ${p.contactTime}`).join(" · ")}
                    </td>
                  </tr>
                );
              } else {
                rows.push(
                  <tr key={r.id} style={{borderBottom:"1px solid var(--border)",cursor:"pointer"}} onClick={()=>onEditRun(ri)}>
                    <td style={S.td}><strong style={{color:"var(--accent)"}}>{r.runNumber}</strong></td>
                    <td style={S.td}>{Fmt.date(r.date)}</td>
                    <td style={S.td}>{dirLabel(r.direction)}</td>
                    <td style={S.td}>{r.frontPig}</td>
                    <td style={S.td}>{r.rearPig!=="None"?r.rearPig:"—"}</td>
                    <td style={S.td}>{r.thirdPig!=="None"?r.thirdPig:"—"}</td>
                    <td style={S.td}>{r.chemType==="Other"?r.chemManualType:r.chemType}</td>
                    <td style={S.td}>{r.chemPercent}</td>
                    <td style={S.td}>{r.chemVolume}g</td>
                    <td style={S.td}>{Fmt.timeShort(r.launchTime)}</td>
                    <td style={S.td}>{Fmt.timeShort(r.receiveTime)}</td>
                    <td style={S.td}>{Fmt.duration(r.duration)}</td>
                    <td style={S.td}>{r.estVolumeOut}g</td>
                    <td style={S.td}>{r.tank}</td>
                    <td style={S.td}>{r.totalSolids}</td>
                    <td style={S.td}>{r.percentAcid}</td>
                    <td style={S.td}>{r.solidColor}</td>
                    <td style={{...S.td,maxWidth:80,overflow:"hidden",textOverflow:"ellipsis"}}>{r.notes||"—"}</td>
                  </tr>
                );
              }
              return rows;
            })}
          </tbody>
        </table>
      </div>
      {runs.length===0&&<div style={{textAlign:"center",padding:40,color:"var(--dim)"}}>No runs yet</div>}

      {/* Coating Runs Section */}
      {coatingDays&&coatingDays.length>0&&(()=>{
        const allCoatingRuns=[];
        coatingDays.forEach(d=>(d.runs||[]).forEach(r=>allCoatingRuns.push({...r,dayLabel:d.label,dayDate:d.date})));
        if(allCoatingRuns.length===0) return null;
        return <div style={{marginTop:20}}>
          <div style={{fontSize:13,fontWeight:900,color:"var(--accent)",textTransform:"uppercase",letterSpacing:"0.1em",marginBottom:8,padding:"0 4px"}}>◎ Coating Runs</div>
          <div style={{overflow:"auto",borderRadius:10,border:"1px solid rgba(255,165,0,0.25)"}}>
            <table style={{borderCollapse:"collapse",fontSize:11,fontFamily:"var(--font)",minWidth:700,width:"100%"}}>
              <thead><tr style={{background:"rgba(255,165,0,0.08)"}}>
                {["Day","Date","Run #","Front","Rear","Launch","Receive","Dur.","Lbs In","Lbs Out","Lbs Applied","Gals/Mil","Lbs/Mil","Mils"].map(h=>(
                  <th key={h} style={{padding:"8px 4px",color:"var(--muted)",fontWeight:700,textTransform:"uppercase",fontSize:8,borderBottom:"2px solid var(--accent)",textAlign:"left",whiteSpace:"nowrap"}}>{h}</th>
                ))}
              </tr></thead>
              <tbody>
                {allCoatingRuns.map(r=>{
                  const ta=(r.totalLbsLoaded||0)-(r.totalLbsUnloaded||0);
                  const mils=Calc.coatingMils(proj,ta);
                  const dur=(r.launchTime&&r.receiveTime)?Fmt.duration(r.receiveTime-r.launchTime):"—";
                  return <tr key={r.id} style={{borderBottom:"1px solid var(--border)"}}>
                    <td style={S.td}>{r.dayLabel}</td>
                    <td style={S.td}>{Fmt.date(r.dayDate)}</td>
                    <td style={{...S.td,fontWeight:800,color:"var(--accent)"}}>#{r.runNumber}</td>
                    <td style={S.td}>{r.frontPig||"—"}</td>
                    <td style={S.td}>{r.rearPig||"—"}</td>
                    <td style={S.td}>{Fmt.timeShort(r.launchTime)}</td>
                    <td style={S.td}>{Fmt.timeShort(r.receiveTime)}</td>
                    <td style={S.td}>{dur}</td>
                    <td style={S.td}>{(r.totalLbsLoaded||0).toLocaleString()}</td>
                    <td style={S.td}>{(r.totalLbsUnloaded||0).toLocaleString()}</td>
                    <td style={{...S.td,fontWeight:700}}>{ta.toLocaleString()}</td>
                    <td style={S.td}>{mils?mils.galsPerMil:"—"}</td>
                    <td style={S.td}>{mils?mils.lbsPerMil:"—"}</td>
                    <td style={{...S.td,fontWeight:900,color:"var(--accent)"}}>{mils?mils.mils+" mils":"—"}</td>
                  </tr>;
                })}
              </tbody>
            </table>
          </div>
        </div>;
      })()}
    </div>
  );
}

function ResultsPage({runs,proj,NavBar}) {
  const t=Calc.projectTotals(runs,proj);
  return (
    <div style={{padding:"12px 16px",maxWidth:CONTAINER_MAX,margin:"0 auto",paddingBottom:80}}>
      <div style={{fontSize:16,fontWeight:900,fontFamily:"var(--display)",textAlign:"center",marginBottom:16}}>RESULTS</div>
      <div style={{...S.card,background:"linear-gradient(135deg,rgba(255,165,0,0.06),rgba(255,109,0,0.04))",border:"1px solid rgba(255,165,0,0.2)"}}>
        <div style={{...S.ct,fontSize:13,marginBottom:14}}>Project Totals</div>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:"12px 16px"}}>
          {[["Total Runs",t.totalRuns],["Total Run Time",t.totalRunTime],["Avg Speed",t.avgSpeedFtSec+" ft/s"],["Total Contact",t.totalContactTime],["Vol Loaded",t.totalVolLoaded.toLocaleString()+" gal"],["Vol Out",t.totalVolOut.toLocaleString()+" gal"],["Pipeline Vol",Number(t.pipelineVol).toLocaleString()+" gal"],["Gal/ft",Calc.galPerFt(Calc.calcDiam(proj)).toFixed(4)]].map(([l,v])=>(
            <div key={l}><div style={S.rl}>{l}</div><div style={S.rv}>{v}</div></div>
          ))}
        </div>
      </div>

      {/* Chemical breakdown by type */}
      {t.chemByType&&Object.keys(t.chemByType).length>0&&<div style={{...S.card,border:"1px solid rgba(255,165,0,0.15)"}}>
        <div style={S.ct}>Chemical Volume by Type</div>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"10px 16px"}}>
          {Object.entries(t.chemByType).map(([type,vol])=>(
            <div key={type}>
              <div style={S.rl}>{type}</div>
              <div style={S.rv}>{vol.toLocaleString()} gal</div>
            </div>
          ))}
        </div>
      </div>}

      {runs.map(r=>{
        const res=Calc.runResults(r,proj);
        return (
          <div key={r.id} style={{...S.card,marginBottom:10}}>
            <div style={{display:"flex",justifyContent:"space-between",marginBottom:8}}>
              <span style={{fontWeight:800,color:"var(--accent)",fontSize:14}}>Run #{r.runNumber}{r.shuttlePasses&&r.shuttlePasses.length>0?" 🔄":""}</span>
              {r.shuttlePasses&&r.shuttlePasses.length>0
                ? <span style={{fontSize:11,color:"#ffab00"}}>{r.shuttlePasses.length} passes</span>
                : <span style={{fontSize:11,color:"var(--dim)"}}>{dirLabel(r.direction)}</span>
              }
            </div>
            {r.shuttlePasses&&r.shuttlePasses.length>0
              ? <div>
                  {r.shuttlePasses.map((p,pi)=>(
                    <div key={pi} style={{background:"rgba(255,165,0,0.04)",borderRadius:8,padding:"8px 10px",marginBottom:6}}>
                      <div style={{fontSize:11,fontWeight:700,color:"var(--accent)",marginBottom:4}}>Pass {pi+1}: {dirLabel(p.direction)}</div>
                      <div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:"4px 12px"}}>
                        {[["Run Time",Fmt.duration(p.duration)],["Contact",p.contactTime],["Launch",Fmt.timeShort(p.launchTime)],["Receive",Fmt.timeShort(p.receiveTime)]].map(([l,v])=>(
                          <div key={l}><div style={S.rl}>{l}</div><div style={{...S.rv,fontSize:12}}>{v}</div></div>
                        ))}
                      </div>
                    </div>
                  ))}
                  <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"8px 16px",marginTop:8}}>
                    {[["Vol Loaded",r.chemVolume+" gal"],["Total Time",Fmt.duration(r.duration)]].map(([l,v])=>(
                      <div key={l}><div style={S.rl}>{l}</div><div style={S.rv}>{v}</div></div>
                    ))}
                  </div>
                </div>
              : <div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:"8px 16px"}}>
                  {[["Batch Length",res.batchLengthFt+" ft"],["Run Time",res.runTime],["Pig Speed",res.speedFtPerSec+" ft/s"],["Contact Time",res.contactTime],["Vol Loaded",r.chemVolume+" gal"],["Direction", r.direction||"—"]].map(([l,v])=>(
                    <div key={l}><div style={S.rl}>{l}</div><div style={S.rv}>{v}</div></div>
                  ))}
                </div>
            }
          </div>
        );
      })}
      {runs.length===0&&<div style={{textAlign:"center",padding:40,color:"var(--dim)"}}>No runs yet</div>}
    </div>
  );
}

function NotesPage({dailyNotes,setTodayNote,todayStr,todayNote,NavBar}) {
  const [viewDate, setViewDate] = React.useState(null);
  const [showDatePicker, setShowDatePicker] = React.useState(false);

  const pastNotes = dailyNotes.filter(n=>n.date!==todayStr&&n.text)
    .sort((a,b)=>new Date(b.date)-new Date(a.date));
  const viewNote = viewDate ? pastNotes.find(n=>n.date===viewDate) : null;

  return (
    <div style={{padding:"12px 16px",maxWidth:CONTAINER_MAX,margin:"0 auto",paddingBottom:80}}>
      <div style={{fontSize:16,fontWeight:900,fontFamily:"var(--display)",textAlign:"center",marginBottom:16}}>DAILY NOTES</div>
      <div style={S.card}>
        <div style={{fontSize:13,fontWeight:700,color:"var(--accent)",marginBottom:8}}>Today — {todayStr}</div>
        <textarea rows={8} placeholder="Type today's notes..." value={todayNote?.text||""} onChange={e=>setTodayNote(e.target.value)} style={{...S.inp,resize:"vertical",minHeight:150,fontSize:14,lineHeight:1.6}} />
      </div>
      {pastNotes.length>0&&<div style={{marginTop:16}}>
        <div style={{fontSize:11,color:"var(--muted)",fontWeight:700,textTransform:"uppercase",marginBottom:8}}>Previous Notes ({pastNotes.length} days)</div>
        <div style={{...S.card,padding:"10px 14px",marginBottom:12}}>
          <label style={S.lb}>Select Date</label>
          <button onClick={()=>setShowDatePicker(true)} style={{...S.ba,width:"100%",padding:"12px",fontSize:14,textAlign:"left"}}>
            📅 {viewDate||"Choose a date..."} {viewDate&&viewDate===pastNotes[0]?.date?"(Most Recent)":""}
          </button>
          {showDatePicker&&<PopupMenu
            title="Select Date"
            options={pastNotes.map(n=>n.date)}
            onSelect={d=>{setViewDate(d);setShowDatePicker(false);}}
            onClose={()=>setShowDatePicker(false)}
          />}
        </div>
        {viewNote&&<div style={{...S.card,padding:"12px 14px",border:"1px solid rgba(255,165,0,0.2)"}}>
          <div style={{fontSize:12,fontWeight:800,color:"var(--accent)",marginBottom:8}}>{viewNote.date}</div>
          <div style={{fontSize:13,whiteSpace:"pre-wrap",lineHeight:1.7,color:"var(--text)"}}>{viewNote.text}</div>
        </div>}
        {!viewDate&&<div style={{textAlign:"center",color:"var(--dim)",fontSize:13,padding:"16px 0"}}>Select a date above to view past notes</div>}
      </div>}
    </div>
  );
}

// ======== DAILY REPORT PAGE ========
function DailyReportPage({proj,runs,dailyNotes,coatingDays,jsas,inspections,photos,NavBar}) {
  const [selDate,setSelDate]=useState(null);
  const [showDayPicker,setShowDayPicker]=useState(false);

  const runsByDate={};
  runs.forEach(r=>{const d=Fmt.date(r.date);if(!runsByDate[d])runsByDate[d]=[];runsByDate[d].push(r)});
  const coatingDates=(coatingDays||[]).map(d=>Fmt.date(d.date)).filter(Boolean);
  const jsaDates=(jsas||[]).map(j=>j.date).filter(Boolean);
  const allDates=[...new Set([...Object.keys(runsByDate),...dailyNotes.filter(n=>n.text).map(n=>n.date),...coatingDates,...jsaDates])].sort((a,b)=>new Date(b)-new Date(a));
  const todayStr=new Date().toLocaleDateString("en-US");
  const displayDate=selDate||todayStr;
  const dayRuns=runsByDate[displayDate]||[];
  const dayNote=dailyNotes.find(n=>n.date===displayDate);
  const dayCoating=(coatingDays||[]).filter(d=>Fmt.date(d.date)===displayDate);
  const dayJSAs=(jsas||[]).filter(j=>j.date===displayDate);

  return (
    <div style={{padding:"12px 16px",maxWidth:500,margin:"0 auto",paddingBottom:80}}>
      <div style={{fontSize:16,fontWeight:900,fontFamily:"var(--display)",textAlign:"center",marginBottom:16}}>DAILY REPORT</div>

      {allDates.length>0&&<div style={{...S.card,padding:"10px 14px"}}>
        <div style={S.ct}>Select Day</div>
        <button onClick={()=>setShowDayPicker(true)} style={{...S.ba,width:"100%",padding:"12px",fontSize:14}}>
          📅 {displayDate}{displayDate===todayStr?" (Today)":""}
        </button>
        {showDayPicker&&<PopupMenu title="Select Day" options={allDates.map(d=>d+(d===todayStr?" (Today)":""))} onSelect={v=>{setSelDate(allDates[allDates.map(d=>d+(d===todayStr?" (Today)":"")).indexOf(v)]);setShowDayPicker(false)}} onClose={()=>setShowDayPicker(false)} />}
      </div>}

      <div style={S.card}>
        <div style={{borderBottom:"2px solid var(--accent)",paddingBottom:12,marginBottom:16}}>
          <div style={{fontSize:20,fontWeight:900,fontFamily:"var(--display)",color:"var(--text)"}}>Internal Pipeline Services – Daily Report</div>
          <div style={{fontSize:13,color:"var(--text)",marginTop:4}}>Client: {proj.client||"—"} | Job #: {proj.jobNumber||"—"}</div>
          <div style={{fontSize:12,color:"var(--text)",opacity:0.7}}>{proj.diameter}" × {Number(proj.length||0).toLocaleString()}ft · {proj.location} · {displayDate}</div>
        </div>
        {dayRuns.length===0&&<div style={{color:"var(--muted)",fontSize:13,marginBottom:12}}>No runs recorded for this day.</div>}
        {dayRuns.length>0&&<div style={{overflow:"auto",borderRadius:8,border:"1px solid var(--border)",marginBottom:16}}>
          <table style={{borderCollapse:"collapse",fontSize:11,fontFamily:"var(--font)",minWidth:900,width:"100%"}}>
            <thead><tr style={{background:"var(--highlight)"}}>
              {["#","Dir","Front","Rear","3rd","Chem","%","Vol","Launch","Rec.","Dur.","VolOut","Tank","Solids","Acid","Color","Notes"].map(h=>(
                <th key={h} style={{padding:"8px 4px",color:"var(--muted)",fontWeight:700,textTransform:"uppercase",fontSize:8,borderBottom:"2px solid var(--accent)",textAlign:"left",whiteSpace:"nowrap"}}>{h}</th>
              ))}
            </tr></thead>
            <tbody>
              {dayRuns.map((r)=>{
                const rows=[];
                if(r.shuttlePasses&&r.shuttlePasses.length>0){
                  r.shuttlePasses.forEach((p,pi)=>{
                    rows.push(
                      <tr key={r.id+"p"+pi} style={{borderBottom:"1px solid var(--border)",background:pi%2===0?"rgba(255,165,0,0.04)":"transparent"}}>
                        <td style={S.td}><strong style={{color:"var(--accent)"}}>{r.runNumber}.{pi+1}</strong></td>
                        <td style={S.td}>{dirLabel(p.direction)}</td>
                        <td style={S.td}>{r.frontPig}</td>
                        <td style={S.td}>{r.rearPig!=="None"?r.rearPig:"—"}</td>
                        <td style={S.td}>{r.thirdPig!=="None"?r.thirdPig:"—"}</td>
                        <td style={S.td}>{r.chemType==="Other"?r.chemManualType:r.chemType}</td>
                        <td style={S.td}>{r.chemPercent}</td>
                        <td style={S.td}>{pi===0?r.chemVolume+"g":"↻"}</td>
                        <td style={S.td}>{Fmt.timeShort(p.launchTime)}</td>
                        <td style={S.td}>{Fmt.timeShort(p.receiveTime)}</td>
                        <td style={S.td}>{Fmt.duration(p.duration)}</td>
                        <td style={S.td}>{pi===0?r.estVolumeOut+"g":"—"}</td>
                        <td style={S.td}>{r.tank}</td>
                        <td style={S.td}>{p.totalSolids||"—"}</td>
                        <td style={S.td}>{p.percentAcid||"—"}</td>
                        <td style={S.td}>{p.solidColor||"—"}</td>
                        <td style={{...S.td,maxWidth:80,overflow:"hidden",textOverflow:"ellipsis"}}>{pi===0?(r.notes||"—"):"—"}</td>
                      </tr>
                    );
                  });
                  rows.push(
                    <tr key={r.id+"ct"} style={{background:"rgba(255,171,0,0.04)"}}>
                      <td colSpan={17} style={{...S.td,fontSize:10,color:"var(--accent)",fontStyle:"italic",paddingLeft:12}}>
                        🔄 Shuttle Run — {r.shuttlePasses.length} passes · Contact per pass: {r.shuttlePasses.map((p,i)=>`Pass ${i+1}: ${p.contactTime}`).join(" · ")}
                      </td>
                    </tr>
                  );
                } else {
                  rows.push(
                    <tr key={r.id} style={{borderBottom:"1px solid var(--border)"}}>
                      <td style={S.td}><strong style={{color:"var(--accent)"}}>{r.runNumber}</strong></td>
                      <td style={S.td}>{dirLabel(r.direction)}</td>
                      <td style={S.td}>{r.frontPig}</td>
                      <td style={S.td}>{r.rearPig!=="None"?r.rearPig:"—"}</td>
                      <td style={S.td}>{r.thirdPig!=="None"?r.thirdPig:"—"}</td>
                      <td style={S.td}>{r.chemType==="Other"?r.chemManualType:r.chemType}</td>
                      <td style={S.td}>{r.chemPercent}</td>
                      <td style={S.td}>{r.chemVolume}g</td>
                      <td style={S.td}>{Fmt.timeShort(r.launchTime)}</td>
                      <td style={S.td}>{Fmt.timeShort(r.receiveTime)}</td>
                      <td style={S.td}>{Fmt.duration(r.duration)}</td>
                      <td style={S.td}>{r.estVolumeOut}g</td>
                      <td style={S.td}>{r.tank}</td>
                      <td style={S.td}>{r.totalSolids}</td>
                      <td style={S.td}>{r.percentAcid}</td>
                      <td style={S.td}>{r.solidColor}</td>
                      <td style={{...S.td,maxWidth:80,overflow:"hidden",textOverflow:"ellipsis"}}>{r.notes||"—"}</td>
                    </tr>
                  );
                }
                return rows;
              })}
            </tbody>
          </table>
        </div>}
        {dayCoating.length>0&&<div style={{borderTop:"1px solid var(--border)",paddingTop:12,marginTop:4}}>
          <div style={{fontWeight:800,color:"var(--accent)",fontSize:13,marginBottom:8}}>Coating</div>
          {dayCoating.map(cd=>(
            <div key={cd.id} style={{marginBottom:8}}>
              <div style={{fontSize:11,fontWeight:700,color:"var(--text)",marginBottom:4}}>{cd.label}</div>
              {(cd.runs||[]).map(cr=>{
                const tl=cr.totalLbsLoaded||0,tu=cr.totalLbsUnloaded||0,ta=tl-tu;
                const mils=Calc.coatingMils(proj,ta);
                return <div key={cr.id} style={{fontSize:12,marginBottom:2,color:"var(--text)"}}>Run #{cr.runNumber}: {tl.toLocaleString()} loaded · {tu.toLocaleString()} unloaded · {ta.toLocaleString()} applied{mils?" · "+mils.mils+" mils":""}</div>;
              })}
            </div>
          ))}
        </div>}
        {/* Full JSA details in daily report */}
        {dayJSAs.length>0&&<div style={{borderTop:"1px solid var(--border)",paddingTop:12,marginTop:4}}>
          <div style={{fontWeight:800,color:"var(--accent)",fontSize:13,marginBottom:8}}>JSAs ({dayJSAs.length})</div>
          {dayJSAs.map((j,idx)=>(
            <div key={j.id} style={{background:"rgba(255,165,0,0.04)",borderRadius:10,padding:12,marginBottom:10,border:"1px solid rgba(255,165,0,0.1)"}}>
              <div style={{fontWeight:800,fontSize:13,color:"var(--text)",marginBottom:4}}>JSA #{idx+1}: {j.tasks&&j.tasks.length>0?j.tasks.map(t=>t.type==="Manual Entry"?t.customLabel||"Manual Entry":t.type).join(", "):"(No tasks)"}</div>
              <div style={{fontSize:11,color:"var(--text)",opacity:0.8,marginBottom:6}}>Supervisor: {j.supervisor||"—"} · Location: {j.location||"—"}</div>
              <div style={{fontSize:11,color:"var(--text)",opacity:0.8,marginBottom:4}}>Task Start: {j.taskStartTime||"—"} · Task End: {j.taskEndTime||"—"}</div>
              {(j.tasks||[]).length>0&&<div style={{fontSize:11,color:"var(--text)",opacity:0.8,marginBottom:4}}>Tasks: {(j.tasks||[]).map(t=>t.type==="Manual Entry"?t.customLabel||"Manual Entry":t.type).join(" | ")}</div>}
              <div style={{fontSize:11,color:"var(--text)",opacity:0.8}}>Crew In: {(j.crewSignIn||[]).map(s=>s.name).join(", ")||"None"} · Crew Out: {(j.crewSignOut||[]).map(s=>s.name).join(", ")||"None"}</div>
              {j.additionalComments&&<div style={{fontSize:11,color:"var(--text)",opacity:0.7,marginTop:4,fontStyle:"italic"}}>Notes: {j.additionalComments}</div>}
            </div>
          ))}
        </div>}
        {/* Man Hours section — only show if any JSA for this day is flagged */}
        {(()=>{
          const msToHours = ms => ms/3600000;
          const fmtHrs = h => { if(!h||h<=0) return "—"; const tm=Math.round(h*60),hr=Math.floor(tm/60),mn=tm%60; return hr>0?`${hr}h ${mn}m`:`${mn}m`; };
          const getTs = s => (s.time&&typeof s.time==="number")?s.time:null;
          const includedJSAs = dayJSAs.filter(j=>j.includeHoursInReport);
          if(includedJSAs.length===0) return null;
          // aggregate per person across included JSAs for day total
          const personMs = {};
          includedJSAs.forEach(jsa=>{
            const inMap={}, outMap={};
            (jsa.crewSignIn||[]).forEach(s=>{const ts=getTs(s);if(s.name&&ts)inMap[s.name]=ts;});
            (jsa.crewSignOut||[]).forEach(s=>{const ts=getTs(s);if(s.name&&ts)outMap[s.name]=ts;});
            const names=[...new Set([...Object.keys(inMap),...Object.keys(outMap)])];
            names.forEach(name=>{
              const inTs=inMap[name]||null, outTs=outMap[name]||null;
              const ms=(inTs&&outTs&&outTs>inTs)?outTs-inTs:null;
              if(ms){if(!personMs[name])personMs[name]=0;personMs[name]+=ms;}
            });
          });
          if(Object.keys(personMs).length===0) return null;
          const dayTotalMs = Object.values(personMs).reduce((s,ms)=>s+ms,0);
          const crewCount = Object.keys(personMs).length;
          // project total across ALL jsas
          const projPersonMs = {};
          (jsas||[]).forEach(jsa=>{
            const inMap={}, outMap={};
            (jsa.crewSignIn||[]).forEach(s=>{const ts=getTs(s);if(s.name&&ts)inMap[s.name]=ts;});
            (jsa.crewSignOut||[]).forEach(s=>{const ts=getTs(s);if(s.name&&ts)outMap[s.name]=ts;});
            const names=[...new Set([...Object.keys(inMap),...Object.keys(outMap)])];
            names.forEach(name=>{
              const inTs=inMap[name]||null, outTs=outMap[name]||null;
              const ms=(inTs&&outTs&&outTs>inTs)?outTs-inTs:null;
              if(ms){if(!projPersonMs[name])projPersonMs[name]=0;projPersonMs[name]+=ms;}
            });
          });
          const projTotalMs = Object.values(projPersonMs).reduce((s,ms)=>s+ms,0);
          return (
            <div style={{borderTop:"1px solid var(--border)",paddingTop:12,marginTop:8}}>
              <div style={{fontWeight:800,color:"var(--accent)",fontSize:13,marginBottom:10}}>⏱ Man Hours</div>
              <div style={{display:"grid",gridTemplateColumns:"1fr auto",gap:"8px 16px",alignItems:"center"}}>
                <div style={{fontSize:12,color:"var(--muted)",fontWeight:600}}>Crew Members</div>
                <div style={{fontSize:14,fontWeight:900,color:"var(--text)",fontFamily:"var(--mono)",textAlign:"right"}}>{crewCount}</div>
                <div style={{fontSize:12,color:"var(--muted)",fontWeight:600}}>Total Hours Today</div>
                <div style={{fontSize:14,fontWeight:900,color:"var(--accent)",fontFamily:"var(--mono)",textAlign:"right"}}>{fmtHrs(msToHours(dayTotalMs))} <span style={{fontSize:11,color:"var(--muted)",fontWeight:400}}>({msToHours(dayTotalMs).toFixed(2)} hrs)</span></div>
                <div style={{fontSize:12,color:"var(--muted)",fontWeight:600}}>Total Hours — Project</div>
                <div style={{fontSize:14,fontWeight:900,color:"var(--text)",fontFamily:"var(--mono)",textAlign:"right"}}>{fmtHrs(msToHours(projTotalMs))} <span style={{fontSize:11,color:"var(--muted)",fontWeight:400}}>({msToHours(projTotalMs).toFixed(2)} hrs)</span></div>
              </div>
            </div>
          );
        })()}
        {dayNote?.text&&<div style={{marginTop:8}}>
          <div style={{fontWeight:800,color:"var(--accent)",fontSize:13,marginBottom:6}}>Field Notes</div>
          <div style={{fontSize:13,whiteSpace:"pre-wrap",lineHeight:1.6,color:"var(--text)"}}>{dayNote.text}</div>
        </div>}
      </div>
      <div style={{display:"flex",gap:8,marginTop:8}}>
        <button onClick={()=>ReportGen.emailDaily(proj,dayRuns,dayNote,displayDate,dayCoating,dayJSAs,inspections,photos,jsas)} style={{...S.bp,flex:1}}>🖨 Print / Save PDF</button>
        <button onClick={()=>{
          const allEmails=[proj.email,...(proj.emails||[])].filter(Boolean);
          if(allEmails.length===0){alert("No email recipients set. Add them in Setup.");return;}
          const subj=encodeURIComponent(`Daily Report – ${proj.client||""} – ${displayDate}`);
          const body=encodeURIComponent(`Please find the daily report for ${displayDate} attached.\n\nClient: ${proj.client||"—"}\nJob #: ${proj.jobNumber||"—"}\nLocation: ${proj.location||"—"}\n\n(Open the attached PDF from the Print/Save PDF button)`);
          window.open(`mailto:${allEmails.join(",")}?subject=${subj}&body=${body}`,"_self");
        }} style={{...S.ba,flex:0.6,padding:"14px 10px",fontSize:13}}>✉️ Email</button>
      </div>
    </div>
  );
}

function FinalReportPage({proj,runs,dailyNotes,coatingDays,inspections,photos,NavBar}) {
  const t=Calc.projectTotals(runs,proj);

  const runDates=runs.map(r=>r.date).filter(Boolean);
  const sd=proj.startDate||(runDates.length>0?Fmt.date(Math.min(...runDates)):"—");
  const ed=proj.endDate||(runDates.length>0?Fmt.date(Math.max(...runDates)):"—");
  const calcSpanDays=(s,e)=>{try{const a=new Date(s),b=new Date(e);if(isNaN(a)||isNaN(b))return null;const diff=Math.round((b-a)/86400000)+1;return diff>0?diff:null;}catch(ex){return null;}};
  const spanDays=calcSpanDays(sd,ed);
  const ud=[...new Set(runs.map(r=>Fmt.date(r.date)))];
  const spanStr=spanDays!=null?`${spanDays} day${spanDays!==1?"s":""}`:`${ud.length} day${ud.length!==1?"s":""}`;
  return (
    <div style={{padding:"12px 16px",maxWidth:540,margin:"0 auto",paddingBottom:80}}>
      <div style={{...S.card,textAlign:"center",padding:"40px 24px",background:"linear-gradient(160deg,#0d1520,#162030)",borderColor:"rgba(255,165,0,0.2)"}}>
        <div style={{fontSize:11,color:"var(--muted)",textTransform:"uppercase",letterSpacing:"0.2em",marginBottom:8}}>Final Project Report</div>
        <div style={{fontSize:26,fontWeight:900,fontFamily:"var(--display)",color:"var(--text)"}}>{proj.diameter}" Pipeline Project</div>
        <div style={{fontSize:14,color:"var(--accent)",marginTop:12,fontWeight:700}}>Client: {proj.client}</div>
        <div style={{fontSize:12,color:"var(--text)",opacity:0.7,marginTop:4}}>{proj.location} · {proj.productType} · Job #: {proj.jobNumber||"—"}</div>
        <div style={{fontSize:12,color:"var(--text)",opacity:0.5,marginTop:4}}>{sd} — {ed}</div>
      </div>
      <div style={S.card}>
        <div style={{fontSize:18,fontWeight:900,fontFamily:"var(--display)",marginBottom:12,color:"var(--text)"}}>Executive Summary</div>
        <div style={{fontSize:13,lineHeight:1.7,color:"var(--text)",opacity:0.9}}>The project consisted of {Number(proj.length||0).toLocaleString()} ft of {proj.diameter}" pipeline located in {proj.location||"the field"}. The project took place from {sd} through {ed}, spanning {spanStr}. A total of {t.totalRuns} pig runs were completed with a cumulative run time of {t.totalRunTime}. The average pig speed was {t.avgSpeedFtSec} ft/sec. Total chemical volume loaded was {t.totalVolLoaded.toLocaleString()} gallons with {t.totalVolOut.toLocaleString()} gallons recovered.</div>
      </div>

      {/* Methodology */}
      <div style={S.card}>
        <div style={{fontSize:18,fontWeight:900,fontFamily:"var(--display)",marginBottom:14,color:"var(--text)"}}>Methodology</div>
        <div style={{display:"flex",flexDirection:"column",gap:14}}>
          <div>
            <div style={{fontSize:13,fontWeight:800,color:"var(--accent)",marginBottom:4}}>A. Data Collection — Batch Samples</div>
            <div style={{fontSize:13,lineHeight:1.7,color:"var(--text)",opacity:0.9}}>Chemical and water flush batches were retrieved from the receiving side of the pipeline. A Camphor test was conducted to verify the removal of hydrocarbons. A quantitative analysis for determining HCL Acid concentration for each HCL batch was carried out by means of titration method. Water Flush samples were analyzed for percent of solids by means of centrifuge.</div>
          </div>
          <div>
            <div style={{fontSize:13,fontWeight:800,color:"var(--accent)",marginBottom:4}}>B. Atmospheric &amp; Desiccant Dryer Data Collection</div>
            <div style={{fontSize:13,lineHeight:1.7,color:"var(--text)",opacity:0.9}}>Atmospheric conditions and the desiccant dryer's dew point were analyzed using a Fluke 971 Temperature Humidity Meter.</div>
          </div>
          <div>
            <div style={{fontSize:13,fontWeight:800,color:"var(--accent)",marginBottom:4}}>C. Water Testing Method</div>
            <div style={{fontSize:13,lineHeight:1.7,color:"var(--text)",opacity:0.9}}>The water used for cleaning batches and water flushes was tested for chloride levels by means of Quantab chloride titration strips in the PPM range of 45 to 480.</div>
          </div>
          <div>
            <div style={{fontSize:13,fontWeight:800,color:"var(--accent)",marginBottom:4}}>D. Epoxy Coating &amp; Surface Profile Data Collection</div>
            <div style={{fontSize:13,lineHeight:1.7,color:"var(--text)",opacity:0.9}}>The epoxy coating's viscosity was measured using a Viscometer. The coating was weighed using a pallet scale and coating samples were weighed using a lab grade digital scale. The coating's temperature was measured using a lab grade infrared temperature gun. The Dry Film Thickness (DFT) is measured using a Mikrotest magnetic coating thickness / PosiTest DFT gauge.</div>
          </div>
        </div>
      </div>

      {/* Chemical breakdown */}
      {t.chemByType&&Object.keys(t.chemByType).length>0&&<div style={S.card}>
        <div style={{fontSize:14,fontWeight:900,fontFamily:"var(--display)",marginBottom:10,color:"var(--text)"}}>Chemical Volume Breakdown</div>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"8px 16px"}}>
          {Object.entries(t.chemByType).map(([type,vol])=>(
            <div key={type}>
              <div style={S.rl}>{type}</div>
              <div style={{...S.rv,color:"var(--text)"}}>{vol.toLocaleString()} gal</div>
            </div>
          ))}
        </div>
      </div>}

      <div style={S.card}>
        <div style={{fontSize:16,fontWeight:900,fontFamily:"var(--display)",marginBottom:8,color:"var(--text)"}}>Run Sheet</div>
        <div style={{overflow:"auto",borderRadius:8,border:"1px solid var(--border)"}}>
          <table style={{borderCollapse:"collapse",fontSize:9,fontFamily:"var(--mono)",width:"100%"}}>
            <thead><tr style={{background:"var(--highlight)"}}>
              {["#","Date","Dir","Pigs","Chem","%","Vol","Launch","Rec.","Dur.","Out","Solids","Acid","Color","Notes"].map(h=>(
                <th key={h} style={{padding:"4px 3px",color:"var(--muted)",fontWeight:700,textTransform:"uppercase",fontSize:7,borderBottom:"2px solid var(--accent)",textAlign:"left",whiteSpace:"nowrap"}}>{h}</th>
              ))}
            </tr></thead>
            <tbody>
              {runs.map((r,ri)=>{
                const rows=[];
                const tdC={padding:"2px 3px",whiteSpace:"nowrap",color:"var(--text)",fontSize:9,borderBottom:"1px solid rgba(0,0,0,0.05)",fontFamily:"var(--mono)"};
                const pigStr=(f,rr,t)=>[f,rr!=="None"?rr:null,t&&t!=="None"?t:null].filter(Boolean).join("/");
                if(r.shuttlePasses&&r.shuttlePasses.length>0){
                  r.shuttlePasses.forEach((p,pi)=>{
                    rows.push(
                      <tr key={r.id+"p"+pi} style={{background:pi%2===0?"rgba(255,165,0,0.025)":"transparent"}}>
                        <td style={{...tdC,fontWeight:800,color:"var(--accent)"}}>{r.runNumber}.{pi+1}</td>
                        <td style={tdC}>{Fmt.date(r.date)}</td>
                        <td style={{...tdC,fontWeight:700,color:p.direction&&p.direction.startsWith("Launch")?"#4fc3f7":"#ffa07a"}}>{dirLabel(p.direction)}</td>
                        <td style={tdC}>{pigStr(r.frontPig,r.rearPig,r.thirdPig)}</td>
                        <td style={tdC}>{r.chemType==="Other"?r.chemManualType:r.chemType}</td>
                        <td style={tdC}>{r.chemPercent}</td>
                        <td style={tdC}>{pi===0?r.chemVolume+"g":"\u21BB"}</td>
                        <td style={tdC}>{Fmt.timeShort(p.launchTime)}</td>
                        <td style={tdC}>{Fmt.timeShort(p.receiveTime)}</td>
                        <td style={tdC}>{Fmt.duration(p.duration)}</td>
                        <td style={tdC}>{pi===0?r.estVolumeOut+"g":"\u2014"}</td>
                        <td style={tdC}>{p.totalSolids||"\u2014"}</td>
                        <td style={tdC}>{p.percentAcid||"\u2014"}</td>
                        <td style={tdC}>{p.solidColor||"\u2014"}</td>
                        <td style={{...tdC,maxWidth:70,overflow:"hidden",textOverflow:"ellipsis"}}>{pi===0?(r.notes||""):"\u2014"}</td>
                      </tr>
                    );
                  });
                } else {
                  rows.push(
                    <tr key={r.id} style={{background:ri%2===0?"rgba(0,0,0,0.02)":"transparent"}}>
                      <td style={{...tdC,fontWeight:800,color:"var(--accent)"}}>{r.runNumber}</td>
                      <td style={tdC}>{Fmt.date(r.date)}</td>
                      <td style={{...tdC,fontWeight:700,color:r.direction&&r.direction.startsWith("Launch")?"#4fc3f7":"#ffa07a"}}>{dirLabel(r.direction)}</td>
                      <td style={tdC}>{pigStr(r.frontPig,r.rearPig,r.thirdPig)}</td>
                      <td style={tdC}>{r.chemType==="Other"?r.chemManualType:r.chemType}</td>
                      <td style={tdC}>{r.chemPercent}</td>
                      <td style={tdC}>{r.chemVolume}g</td>
                      <td style={tdC}>{Fmt.timeShort(r.launchTime)}</td>
                      <td style={tdC}>{Fmt.timeShort(r.receiveTime)}</td>
                      <td style={tdC}>{Fmt.duration(r.duration)}</td>
                      <td style={tdC}>{r.estVolumeOut}g</td>
                      <td style={tdC}>{r.totalSolids||"\u2014"}</td>
                      <td style={tdC}>{r.percentAcid||"\u2014"}</td>
                      <td style={tdC}>{r.solidColor||"\u2014"}</td>
                      <td style={{...tdC,maxWidth:70,overflow:"hidden",textOverflow:"ellipsis"}}>{r.notes||""}</td>
                    </tr>
                  );
                }
                return rows;
              })}
            </tbody>
          </table>
        </div>
      </div>
      {dailyNotes.filter(n=>n.text).length>0&&<div style={S.card}>
        <div style={{fontSize:18,fontWeight:900,fontFamily:"var(--display)",marginBottom:12,color:"var(--text)"}}>Daily Notes</div>
        {dailyNotes.filter(n=>n.text).map((n,i)=>(
          <div key={i} style={{marginBottom:12,borderLeft:"3px solid var(--accent)",paddingLeft:12}}>
            <div style={{fontSize:12,fontWeight:800,color:"var(--accent)",marginBottom:2}}>{n.date}</div>
            <div style={{fontSize:13,whiteSpace:"pre-wrap",lineHeight:1.6,color:"var(--text)"}}>{n.text}</div>
          </div>
        ))}
      </div>}
      {coatingDays&&coatingDays.length>0&&<div style={S.card}>
        <div style={{fontSize:16,fontWeight:900,fontFamily:"var(--display)",marginBottom:12,color:"var(--text)"}}>Coating Summary</div>
        {coatingDays.map(d=>{
          let tl=0,tu=0;
          (d.runs||[]).forEach(r=>{tl+=r.totalLbsLoaded||0;tu+=r.totalLbsUnloaded||0});
          const ta=tl-tu, mils=Calc.coatingMils(proj,ta);
          return <div key={d.id} style={{borderBottom:"1px solid var(--border)",paddingBottom:8,marginBottom:8}}>
            <div style={{fontWeight:700,color:"var(--accent)",fontSize:12,marginBottom:4}}>{d.label} — {Fmt.date(d.date)}</div>
            <div style={{fontSize:12,color:"var(--text)",opacity:0.8}}>Loaded: {tl.toLocaleString()} lbs · Applied: {ta.toLocaleString()} lbs{mils?" · "+mils.mils+" mils":""}</div>
          </div>;
        })}
        {(()=>{let tl=0,tu=0;coatingDays.forEach(d=>(d.runs||[]).forEach(r=>{tl+=r.totalLbsLoaded||0;tu+=r.totalLbsUnloaded||0}));const ta=tl-tu,mils=Calc.coatingMils(proj,ta);return <div style={{marginTop:8,fontWeight:700,color:"var(--text)"}}><span style={{color:"var(--muted)"}}>Total Applied: </span>{ta.toLocaleString()} lbs{mils?" — "+mils.mils+" total mils":""}</div>})()}
      </div>}
      {inspections&&inspections.length>0&&(()=>{
        const ORIS=["12 o'clock","3 o'clock","6 o'clock","9 o'clock"];
        const avgOf=vals=>{const ns=vals.map(v=>parseFloat(v)).filter(v=>!isNaN(v));return ns.length>0?(ns.reduce((a,b)=>a+b,0)/ns.length):null;};
        const fmtA=v=>v!=null?v.toFixed(2):"—";
        const calcLocAvg=loc=>{const avgs=ORIS.map(o=>avgOf(loc.readings[o]||[])).filter(v=>v!=null);return avgs.length>0?avgs.reduce((a,b)=>a+b,0)/avgs.length:null;};
        const overall=()=>{const avgs=inspections.map(l=>calcLocAvg(l)).filter(v=>v!=null);return avgs.length>0?avgs.reduce((a,b)=>a+b,0)/avgs.length:null;};
        return <div style={S.card}>
          <div style={{fontSize:16,fontWeight:900,fontFamily:"var(--display)",marginBottom:12,color:"var(--text)"}}>DFT Inspection Results</div>
          {inspections.map(loc=>{
            const la=calcLocAvg(loc);
            return <div key={loc.id} style={{borderBottom:"1px solid var(--border)",paddingBottom:12,marginBottom:12}}>
              <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:8}}>
                <div><div style={{fontSize:13,fontWeight:800,color:"var(--accent)"}}>{loc.name}</div><div style={{fontSize:10,color:"var(--muted)"}}>{loc.date}</div></div>
                <div style={{fontSize:18,fontWeight:900,color:"var(--accent)",fontFamily:"var(--mono)",border:"1px solid rgba(255,165,0,0.4)",padding:"4px 10px",borderRadius:8}}>{fmtA(la)} mils</div>
              </div>
              <div style={{display:"grid",gridTemplateColumns:"repeat(4,1fr)",gap:6}}>
                {ORIS.map(ori=>{const rv=loc.readings[ori]||["","",""],a=avgOf(rv);return(
                  <div key={ori} style={{background:"rgba(0,0,0,0.04)",borderRadius:8,padding:"6px 8px",textAlign:"center"}}>
                    <div style={{fontSize:9,color:"var(--muted)",fontWeight:700,marginBottom:3}}>{ori}</div>
                    <div style={{fontSize:11,color:"var(--text)"}}>{rv.filter(v=>v!=="").join(" / ")||"—"}</div>
                    <div style={{fontSize:12,fontWeight:800,color:"var(--text)",marginTop:2}}>avg: {fmtA(a)}</div>
                  </div>
                );})}
              </div>
            </div>;
          })}
          {inspections.length>1&&<div style={{display:"flex",justifyContent:"space-between",alignItems:"center",paddingTop:8}}>
            <div style={{fontSize:13,fontWeight:900,color:"var(--text)"}}>Total Average DFT</div>
            <div style={{fontSize:20,fontWeight:900,color:"var(--accent)",fontFamily:"var(--mono)",border:"2px solid var(--accent)",padding:"4px 12px",borderRadius:8}}>{fmtA(overall())} mils</div>
          </div>}
        </div>;
      })()}

      <div style={{display:"flex",gap:8,marginTop:16}}>
        <button onClick={()=>ReportGen.emailFinal(proj,runs,dailyNotes,coatingDays,null,inspections,photos)} style={{...S.bp,flex:1}}>🖨 Print / Save PDF</button>
        <button onClick={()=>{
          const allEmails=[proj.email,...(proj.emails||[])].filter(Boolean);
          if(allEmails.length===0){alert("No email recipients set. Add them in Setup.");return;}
          const subj=encodeURIComponent(`Final Report – ${proj.client||""} – ${proj.diameter}" x ${proj.length}ft`);
          const body=encodeURIComponent(`Please find the final project report attached.\n\nClient: ${proj.client||"—"}\nJob #: ${proj.jobNumber||"—"}\nLocation: ${proj.location||"—"}\nLine: ${proj.diameter||"—"}" × ${Number(proj.length||0).toLocaleString()}ft\n\n(Open from the Print/Save PDF button)`);
          window.open(`mailto:${allEmails.join(",")}?subject=${subj}&body=${body}`,"_self");
        }} style={{...S.ba,flex:0.6,padding:"14px 10px",fontSize:13}}>✉️ Email</button>
      </div>
    </div>
  );
}

function ArchivePage({proj,runs,dailyNotes,coatingDays,jsas,deliveries,compData,inspections,checklist,photos,NavBar}) {
  const { useState } = React;
  const [building, setBuilding] = useState(false);

  const dayNotesCount = (dailyNotes||[]).filter(n=>n.text).length;
  const compsCount = (compData&&compData.comps)||[];
  const checklistItemsCount = (checklist||[]).reduce((sum,s)=>sum+((s.items||[]).length),0);

  const counts = [
    {label:"Runs", n:(runs||[]).length},
    {label:"Coating Days", n:(coatingDays||[]).length},
    {label:"JSAs", n:(jsas||[]).length},
    {label:"Deliveries/Pickups/Fuel", n:(deliveries||[]).length},
    {label:"Compressors Tracked", n:compsCount.length},
    {label:"Inspection Locations", n:(inspections||[]).length},
    {label:"Checklist Items", n:checklistItemsCount},
    {label:"Daily Notes", n:dayNotesCount},
    {label:"Photos", n:(photos||[]).length},
  ];

  const handleGenerate = async () => {
    setBuilding(true);
    try {
      await ReportGen.emailArchive(proj,runs,dailyNotes,coatingDays,jsas,deliveries,compData,inspections,checklist,photos);
    } finally {
      setBuilding(false);
    }
  };

  return (
    <div style={{padding:"12px 16px",maxWidth:540,margin:"0 auto",paddingBottom:80}}>
      <div style={{...S.card,textAlign:"center",padding:"32px 24px",background:"linear-gradient(160deg,#0d1520,#162030)",borderColor:"rgba(255,165,0,0.2)"}}>
        <div style={{fontSize:11,color:"var(--muted)",textTransform:"uppercase",letterSpacing:"0.2em",marginBottom:8}}>Complete Project Archive</div>
        <div style={{fontSize:22,fontWeight:900,fontFamily:"var(--display)",color:"var(--text)"}}>{proj.projectNumber} {proj.client?"— "+proj.client:""}</div>
        <div style={{fontSize:12,color:"var(--text)",opacity:0.6,marginTop:8,lineHeight:1.6}}>
          This generates one PDF containing every piece of data stored for this project — not just the client-facing summary in Final Report. Use this to save a complete backup before removing an old project from the app.
        </div>
      </div>

      <div style={S.card}>
        <div style={{fontSize:14,fontWeight:900,fontFamily:"var(--display)",marginBottom:12,color:"var(--text)"}}>What's included</div>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"8px 16px"}}>
          {counts.map(c=>(
            <div key={c.label} style={{display:"flex",justifyContent:"space-between",fontSize:13,padding:"4px 0",borderBottom:"1px solid var(--border)"}}>
              <span style={{color:"var(--muted)"}}>{c.label}</span>
              <span style={{fontWeight:800,color:c.n>0?"var(--text)":"var(--dim)"}}>{c.n}</span>
            </div>
          ))}
        </div>
      </div>

      <div style={{...S.card,background:"rgba(255,165,0,0.06)",borderColor:"rgba(255,165,0,0.25)"}}>
        <div style={{fontSize:12,color:"var(--text)",lineHeight:1.6}}>
          ⚠️ <b>This does not delete anything.</b> It only creates a PDF. Save it somewhere safe (e.g. Dropbox) and confirm it looks complete before deleting the project from the app yourself — deleting a project is permanent and separate from this export.
        </div>
      </div>

      <button onClick={handleGenerate} disabled={building} style={{...S.bp,marginTop:4,opacity:building?0.6:1}}>
        {building ? "⏳ Building Archive…" : "🗄 Generate Complete Archive PDF"}
      </button>
    </div>
  );
}

