(function(){
  const money = n => (Number(n)||0).toLocaleString(undefined,{minimumFractionDigits:2,maximumFractionDigits:2});
  const num = el => Number(el && el.value ? el.value : 0);
  const products = window.FQS_PRODUCTS || [];
  const batterySizes = [50,65,100,120,150,200,250,300];

  // ── LOCAL-ONLY pre-filled rows (Imported Materials toggle is OFF) ───────────
  // Matches the professional Fortunes format from image 1.
  const defaultLocalOnlyRows = {
    'On-Grid Solar System': [
      {product_category:'Inverter',     product_name:'Inverter',                         description:'Supply, installation, testing & commissioning of on-grid solar inverter; MPPT ≥2; Max DC ≥1100V; Efficiency ≥98%; THD <3%; PF adjustable; protections: anti-islanding, over/under voltage, surge; IP65; communication RS485/WiFi; IEC 62109 compliant; complete with accessories.', brand:'', model:'', qty:1,   unit:'Pcs',     unit_price:0},
      {product_category:'Accessories', product_name:'Energy Meter',                      description:'Supply, installation & commissioning of 3-phase, 4-wire smart bidirectional energy meter; measures import/export kWh; DLMS/COSEM; RF/PLC/RS485; AMI compatible; IEC 62052/62053 compliant; SREDA & utility approved; warranty 5 years.', brand:'', model:'', qty:1,   unit:'lot',     unit_price:0},
      {product_category:'Solar Panel', product_name:'PV Panel',                          description:'Supply, installation, testing & commissioning of mono-crystalline N-type bifacial PV modules; Capacity ≥590Wp; Efficiency ≥21%; Voltage ≥1500V DC; Aluminium frame; IP68 junction box; MC4 compatible; IEC 61215/61730 compliant; 30-year performance warranty.', brand:'', model:'', qty:1,   unit:'Pcs',     unit_price:0},
      {product_category:'Structure',   product_name:'Structure',                         description:'Supply, fabrication & installation of hot-dip galvanised MS mounting structure for solar PV system; wind load ≥2400Pa; corrosion resistant; suitable tilt angle; stainless steel fasteners; complete with foundation, clamps & accessories; approved by Engineer-in-Charge; warranty 2 years.', brand:'Local', model:'-', qty:1,   unit:'Lot',     unit_price:0},
      {product_category:'Cable',       product_name:'DC Cable',                          description:'(PV cable) 4 sq.mm, (2 COIL) – 2 color (Red & Black)',                                                                                                                                                                  brand:'',      model:'',  qty:1,   unit:'2 color', unit_price:0},
      {product_category:'Accessories', product_name:'Electrical Accessories',            description:'MCCB, AC Combiner box included.',                                                                                                                                                                                          brand:'',      model:'',  qty:1,   unit:'Lot',     unit_price:0},
      {product_category:'Cable',       product_name:'AC Cable',                          description:'Cable, (Inverter to AC Combiner Box) (Estimated Price is calculated, if extra cable needed, will be added at actual)',                                                                                                     brand:'',      model:'',  qty:1,   unit:'Lot',     unit_price:0},
      {product_category:'Installation',product_name:'AC-DC Work and Commissioning Fee',  description:'N/A',                                                                                                                                                                                                                      brand:'N/A',   model:'N/A',qty:1,  unit:'kWp',    unit_price:0},
      {product_category:'Service',     product_name:'Load Unload & Labour',              description:'N/A',                                                                                                                                                                                                                      brand:'N/A',   model:'N/A',qty:1,  unit:'lot',    unit_price:0},
      {product_category:'Service',     product_name:'Transport and Delivery',            description:'N/A',                                                                                                                                                                                                                      brand:'N/A',   model:'N/A',qty:1,  unit:'lot',    unit_price:0}
    ],
    'Off-Grid Solar System': [
      {product_category:'Inverter',     product_name:'Inverter',                         description:'Supply, installation, testing & commissioning of off-grid solar inverter; complete with accessories.',                                                                                                                      brand:'', model:'', qty:1,   unit:'Pcs',     unit_price:0},
      {product_category:'Accessories', product_name:'Energy Meter',                      description:'Supply, installation & commissioning of smart energy meter; measures import/export kWh; DLMS/COSEM compatible; utility approved; warranty 5 years.',                                                                       brand:'', model:'', qty:1,   unit:'lot',     unit_price:0},
      {product_category:'Solar Panel', product_name:'PV Panel',                          description:'Supply, installation, testing & commissioning of mono-crystalline PV modules; Capacity ≥590Wp; Efficiency ≥21%; Aluminium frame; IP68 junction box; MC4 compatible; IEC 61215/61730 compliant; 30-year performance warranty.', brand:'', model:'', qty:1,   unit:'Pcs',     unit_price:0},
      {product_category:'Battery',     product_name:'Battery / BESS',                   description:'Supply & installation of battery energy storage system; complete with BMS and accessories.',                                                                                                                                 brand:'', model:'', qty:1,   unit:'Set',     unit_price:0},
      {product_category:'Structure',   product_name:'Structure',                         description:'Supply, fabrication & installation of hot-dip galvanised MS mounting structure; wind load ≥2400Pa; suitable tilt angle; stainless steel fasteners; approved by Engineer-in-Charge; warranty 2 years.',                    brand:'Local', model:'-', qty:1,   unit:'Lot',     unit_price:0},
      {product_category:'Cable',       product_name:'DC Cable',                          description:'(PV cable) 4 sq.mm, (2 COIL) – 2 color (Red & Black)',                                                                                                                                                                  brand:'',      model:'',  qty:1,   unit:'2 color', unit_price:0},
      {product_category:'Accessories', product_name:'Electrical Accessories',            description:'MCCB, AC Combiner box included.',                                                                                                                                                                                          brand:'',      model:'',  qty:1,   unit:'Lot',     unit_price:0},
      {product_category:'Cable',       product_name:'AC Cable',                          description:'Cable, (Inverter to AC Combiner Box) (Estimated Price is calculated, if extra cable needed, will be added at actual)',                                                                                                     brand:'',      model:'',  qty:1,   unit:'Lot',     unit_price:0},
      {product_category:'Installation',product_name:'AC-DC Work and Commissioning Fee',  description:'N/A',                                                                                                                                                                                                                      brand:'N/A',   model:'N/A',qty:1,  unit:'kWp',    unit_price:0},
      {product_category:'Service',     product_name:'Load Unload & Labour',              description:'N/A',                                                                                                                                                                                                                      brand:'N/A',   model:'N/A',qty:1,  unit:'lot',    unit_price:0},
      {product_category:'Service',     product_name:'Transport and Delivery',            description:'N/A',                                                                                                                                                                                                                      brand:'N/A',   model:'N/A',qty:1,  unit:'lot',    unit_price:0}
    ],
    'Hybrid Solar System': [
      {product_category:'Inverter',     product_name:'Inverter',                         description:'Supply, installation, testing & commissioning of 10kW 3-phase grid-tied hybrid inverter; MPPT ≥2; Max DC ≥1100V; AC output 3-phase 400V, 50Hz; Efficiency ≥98%; THD <3%; PF adjustable; protections: anti-islanding, over/under voltage, surge; IP65; communication RS485/WiFi; IEC 62109 compliant; complete with accessories.', brand:'', model:'', qty:1,   unit:'Pcs',     unit_price:0},
      {product_category:'Accessories', product_name:'Energy Meter',                      description:'Supply, installation & commissioning of 3-phase, 4-wire smart bidirectional energy meter; Voltage 3×230/400V; Current 5-60A/100A; Accuracy Class 1.0; measures import/export kWh; DLMS/COSEM; RF/PLC/RS485; AMI compatible; IEC 62052/62053 compliant; SREDA & utility approved; warranty 5 years.',                              brand:'', model:'', qty:1,   unit:'lot',     unit_price:0},
      {product_category:'Solar Panel', product_name:'PV Panel',                          description:'Supply, installation, testing & commissioning of mono-crystalline N-type bifacial PV modules; Capacity ≥590Wp; Efficiency ≥21%; Voltage ≥1500V DC; Voc ≥47V; Imp ≥13A; Positive tolerance; Aluminium frame; IP68 junction box; MC4 compatible; IEC 61215/61730 compliant; 30-year performance warranty.',                         brand:'', model:'', qty:1,   unit:'Pcs',     unit_price:0},
      {product_category:'Battery',     product_name:'Battery / BESS',                   description:'Supply & installation of battery energy storage system; complete with BMS and accessories.',                                                                                                                                 brand:'', model:'', qty:1,   unit:'Set',     unit_price:0},
      {product_category:'Structure',   product_name:'Structure',                         description:'Supply, fabrication & installation of hot-dip galvanised MS mounting structure for solar PV system; wind load ≥2400Pa; corrosion resistant; suitable tilt angle; stainless steel fasteners; complete with foundation, clamps & accessories; approved by Engineer-in-Charge; warranty 2 years.',                                      brand:'Local', model:'-', qty:1,   unit:'Lot',     unit_price:0},
      {product_category:'Cable',       product_name:'DC Cable',                          description:'(PV cable) 4 sq.mm, (2 COIL) – 2 color (Red & Black)',                                                                                                                                                                  brand:'',      model:'',  qty:1,   unit:'2 color', unit_price:0},
      {product_category:'Accessories', product_name:'Electrical Accessories',            description:'MCCB, AC Combiner box included.',                                                                                                                                                                                          brand:'',      model:'',  qty:1,   unit:'Lot',     unit_price:0},
      {product_category:'Cable',       product_name:'AC Cable',                          description:'Cable, (Inverter to AC Combiner Box) (Estimated Price is calculated, if extra cable needed, will be added at actual)',                                                                                                     brand:'',      model:'',  qty:1,   unit:'Lot',     unit_price:0},
      {product_category:'Installation',product_name:'AC-DC Work and Commissioning Fee',  description:'N/A',                                                                                                                                                                                                                      brand:'N/A',   model:'N/A',qty:1,  unit:'kWp',    unit_price:0},
      {product_category:'Service',     product_name:'Load Unload & Labour',              description:'N/A',                                                                                                                                                                                                                      brand:'N/A',   model:'N/A',qty:1,  unit:'lot',    unit_price:0},
      {product_category:'Service',     product_name:'Transport and Delivery',            description:'N/A',                                                                                                                                                                                                                      brand:'N/A',   model:'N/A',qty:1,  unit:'lot',    unit_price:0}
    ],
    'Solar Water Pumping System': [
      {product_category:'Inverter',     product_name:'Pump Inverter / VFD',              description:'Supply, installation, testing & commissioning of solar pump inverter/VFD; complete with accessories.',                                                                                                                      brand:'', model:'', qty:1,   unit:'Pcs',     unit_price:0},
      {product_category:'Solar Panel', product_name:'PV Panel',                          description:'Supply, installation, testing & commissioning of mono-crystalline PV modules; Aluminium frame; IP68 junction box; IEC compliant; 30-year performance warranty.',                                                           brand:'', model:'', qty:1,   unit:'Pcs',     unit_price:0},
      {product_category:'Structure',   product_name:'Structure',                         description:'Supply, fabrication & installation of hot-dip galvanised MS mounting structure; wind load ≥2400Pa; suitable tilt angle; stainless steel fasteners; approved by Engineer-in-Charge; warranty 2 years.',                    brand:'Local', model:'-', qty:1,   unit:'Lot',     unit_price:0},
      {product_category:'Cable',       product_name:'DC Cable',                          description:'(PV cable) 4 sq.mm, (2 COIL) – 2 color (Red & Black)',                                                                                                                                                                  brand:'',      model:'',  qty:1,   unit:'2 color', unit_price:0},
      {product_category:'Accessories', product_name:'Electrical Accessories',            description:'MCCB, AC Combiner box included.',                                                                                                                                                                                          brand:'',      model:'',  qty:1,   unit:'Lot',     unit_price:0},
      {product_category:'Cable',       product_name:'AC Cable',                          description:'Cable, (Pump to AC Combiner Box) (Estimated Price is calculated, if extra cable needed, will be added at actual)',                                                                                                         brand:'',      model:'',  qty:1,   unit:'Lot',     unit_price:0},
      {product_category:'Installation',product_name:'AC-DC Work and Commissioning Fee',  description:'N/A',                                                                                                                                                                                                                      brand:'N/A',   model:'N/A',qty:1,  unit:'kWp',    unit_price:0},
      {product_category:'Service',     product_name:'Transport and Delivery',            description:'N/A',                                                                                                                                                                                                                      brand:'N/A',   model:'N/A',qty:1,  unit:'lot',    unit_price:0}
    ]
  };

  // ── LOCAL PART rows when "Imported Materials Included" is ON ──────────────
  // These are the "Local Part" items from images 3-4 (the import+local format).
  const importedLocalPartRows = {
    'On-Grid Solar System': [
      {product_category:'Service',      product_name:'Engineering, Design, Drawing',            description:'N/A',                                                                                                                                     brand:'N/A',          model:'N/A', qty:1,   unit:'Lot',  unit_price:0},
      {product_category:'Installation', product_name:'Machine for install & lifting all equipment', description:'Materials for install & lifting all equipment',                                                                                      brand:'N/A',          model:'N/A', qty:1,   unit:'kWp',  unit_price:0},
      {product_category:'Accessories',  product_name:'Electrical Accessories',                  description:'MCCB/ABB, AC Combiner box included. Local energy meter will be installing for each inverter.',                                           brand:'ABB/ Schneider',model:'ABB/ Schinder',qty:1,unit:'Lot',unit_price:0},
      {product_category:'Cable',        product_name:'AC Cable (As per site length may change)', description:'Cable, (Inverter to AC Combiner Box) (Estimated Price is calculated)',                                                                  brand:'BRB/BBS/ SQ',  model:'',    qty:1,   unit:'Lot',  unit_price:0},
      {product_category:'Cable',        product_name:'Grounding Cable (As per site length may change)', description:'Aluminum Cable',                                                                                                                 brand:'BRB/BBS/ SQ',  model:'50 mm Earting',qty:1,unit:'Lot',unit_price:0},
      {product_category:'Cable',        product_name:'Communication Cable (As per site length may change)', description:'Cat 6',                                                                                                                      brand:'BRB',          model:'N/A', qty:200, unit:'Mtr.', unit_price:0},
      {product_category:'Accessories',  product_name:'Cable Ladder (As per site length may change)', description:'N/A',                                                                                                                               brand:'N/A',          model:'N/A', qty:400, unit:'Ft.',  unit_price:0},
      {product_category:'Accessories',  product_name:'Cable Tray (As per site length may change)', description:'200 mm sizing',                                                                                                                       brand:'N/A',          model:'N/A', qty:400, unit:'Ft.',  unit_price:0},
      {product_category:'Installation', product_name:'AC-DC Work and Commissioning Fee',         description:'N/A',                                                                                                                                   brand:'N/A',          model:'N/A', qty:1,   unit:'kWp',  unit_price:0},
      {product_category:'Installation', product_name:'Install LPS System',                       description:'For the Plant and Factory (OPR 60, Earthling ROD, with boring and accessories)',                                                        brand:'N/A',          model:'N/A', qty:1,   unit:'Lot',  unit_price:0},
      {product_category:'Service',      product_name:'Transport and Delivery',                   description:'N/A',                                                                                                                                   brand:'N/A',          model:'N/A', qty:1,   unit:'lot',  unit_price:0},
      {product_category:'Service',      product_name:'Cleaning Systems',                         description:'Manual, (Motor, nozzle, pipe etc.) (As per site)',                                                                                      brand:'N/A',          model:'N/A', qty:1,   unit:'lot',  unit_price:0}
    ],
    'Off-Grid Solar System': [
      {product_category:'Service',      product_name:'Engineering, Design, Drawing',            description:'N/A',                                                                                                                                     brand:'N/A',          model:'N/A', qty:1,   unit:'Lot',  unit_price:0},
      {product_category:'Installation', product_name:'Machine for install & lifting all equipment', description:'Materials for install & lifting all equipment',                                                                                      brand:'N/A',          model:'N/A', qty:1,   unit:'kWp',  unit_price:0},
      {product_category:'Accessories',  product_name:'Electrical Accessories',                  description:'MCCB/ABB, AC Combiner box included. Local energy meter will be installing for each inverter.',                                           brand:'ABB/ Schneider',model:'ABB/ Schinder',qty:1,unit:'Lot',unit_price:0},
      {product_category:'Cable',        product_name:'AC Cable (As per site length may change)', description:'Cable, (Inverter to AC Combiner Box) (Estimated Price is calculated)',                                                                  brand:'BRB/BBS/ SQ',  model:'',    qty:1,   unit:'Lot',  unit_price:0},
      {product_category:'Cable',        product_name:'Grounding Cable (As per site length may change)', description:'Aluminum Cable',                                                                                                                 brand:'BRB/BBS/ SQ',  model:'50 mm Earting',qty:1,unit:'Lot',unit_price:0},
      {product_category:'Cable',        product_name:'Communication Cable (As per site length may change)', description:'Cat 6',                                                                                                                      brand:'BRB',          model:'N/A', qty:200, unit:'Mtr.', unit_price:0},
      {product_category:'Accessories',  product_name:'Cable Ladder (As per site length may change)', description:'N/A',                                                                                                                               brand:'N/A',          model:'N/A', qty:400, unit:'Ft.',  unit_price:0},
      {product_category:'Accessories',  product_name:'Cable Tray (As per site length may change)', description:'200 mm sizing',                                                                                                                       brand:'N/A',          model:'N/A', qty:400, unit:'Ft.',  unit_price:0},
      {product_category:'Installation', product_name:'AC-DC Work and Commissioning Fee',         description:'N/A',                                                                                                                                   brand:'N/A',          model:'N/A', qty:1,   unit:'kWp',  unit_price:0},
      {product_category:'Installation', product_name:'Install LPS System',                       description:'For the Plant and Factory (OPR 60, Earthling ROD, with boring and accessories)',                                                        brand:'N/A',          model:'N/A', qty:1,   unit:'Lot',  unit_price:0},
      {product_category:'Service',      product_name:'Transport and Delivery',                   description:'N/A',                                                                                                                                   brand:'N/A',          model:'N/A', qty:1,   unit:'lot',  unit_price:0},
      {product_category:'Service',      product_name:'Cleaning Systems',                         description:'Manual, (Motor, nozzle, pipe etc.) (As per site)',                                                                                      brand:'N/A',          model:'N/A', qty:1,   unit:'lot',  unit_price:0}
    ],
    'Hybrid Solar System': [
      {product_category:'Service',      product_name:'Engineering, Design, Drawing',            description:'N/A',                                                                                                                                     brand:'N/A',          model:'N/A', qty:1,   unit:'Lot',  unit_price:0},
      {product_category:'Installation', product_name:'Machine for install & lifting all equipment', description:'Materials for install & lifting all equipment',                                                                                      brand:'N/A',          model:'N/A', qty:1,   unit:'kWp',  unit_price:0},
      {product_category:'Accessories',  product_name:'Electrical Accessories',                  description:'MCCB/ABB, AC Combiner box included. Local energy meter will be installing for each inverter.',                                           brand:'ABB/ Schneider',model:'ABB/ Schinder',qty:1,unit:'Lot',unit_price:0},
      {product_category:'Cable',        product_name:'AC Cable (As per site length may change)', description:'Cable, (Inverter to AC Combiner Box) (Estimated Price is calculated)',                                                                  brand:'BRB/BBS/ SQ',  model:'',    qty:1,   unit:'Lot',  unit_price:0},
      {product_category:'Cable',        product_name:'Grounding Cable (As per site length may change)', description:'Aluminum Cable',                                                                                                                 brand:'BRB/BBS/ SQ',  model:'50 mm Earting',qty:1,unit:'Lot',unit_price:0},
      {product_category:'Cable',        product_name:'Communication Cable (As per site length may change)', description:'Cat 6',                                                                                                                      brand:'BRB',          model:'N/A', qty:200, unit:'Mtr.', unit_price:0},
      {product_category:'Accessories',  product_name:'Cable Ladder (As per site length may change)', description:'N/A',                                                                                                                               brand:'N/A',          model:'N/A', qty:400, unit:'Ft.',  unit_price:0},
      {product_category:'Accessories',  product_name:'Cable Tray (As per site length may change)', description:'200 mm sizing',                                                                                                                       brand:'N/A',          model:'N/A', qty:400, unit:'Ft.',  unit_price:0},
      {product_category:'Installation', product_name:'AC-DC Work and Commissioning Fee',         description:'N/A',                                                                                                                                   brand:'N/A',          model:'N/A', qty:1,   unit:'kWp',  unit_price:0},
      {product_category:'Installation', product_name:'Install LPS System',                       description:'For the Plant and Factory (OPR 60, Earthling ROD, with boring and accessories)',                                                        brand:'N/A',          model:'N/A', qty:1,   unit:'Lot',  unit_price:0},
      {product_category:'Service',      product_name:'Transport and Delivery',                   description:'N/A',                                                                                                                                   brand:'N/A',          model:'N/A', qty:1,   unit:'lot',  unit_price:0},
      {product_category:'Service',      product_name:'Cleaning Systems',                         description:'Manual, (Motor, nozzle, pipe etc.) (As per site)',                                                                                      brand:'N/A',          model:'N/A', qty:1,   unit:'lot',  unit_price:0}
    ],
    'Solar Water Pumping System': [
      {product_category:'Service',      product_name:'Engineering, Design, Drawing',            description:'N/A',                                                                                                                                     brand:'N/A',          model:'N/A', qty:1,   unit:'Lot',  unit_price:0},
      {product_category:'Installation', product_name:'Machine for install & lifting all equipment', description:'Materials for install & lifting all equipment',                                                                                      brand:'N/A',          model:'N/A', qty:1,   unit:'kWp',  unit_price:0},
      {product_category:'Accessories',  product_name:'Electrical Accessories',                  description:'MCCB/ABB, AC Combiner box included.',                                                                                                    brand:'ABB/ Schneider',model:'',    qty:1,   unit:'Lot',  unit_price:0},
      {product_category:'Cable',        product_name:'AC Cable (As per site length may change)', description:'Cable, (Pump to AC Combiner Box) (Estimated Price is calculated)',                                                                      brand:'BRB/BBS/ SQ',  model:'',    qty:1,   unit:'Lot',  unit_price:0},
      {product_category:'Cable',        product_name:'Grounding Cable (As per site length may change)', description:'Aluminum Cable',                                                                                                                 brand:'BRB/BBS/ SQ',  model:'50 mm Earting',qty:1,unit:'Lot',unit_price:0},
      {product_category:'Installation', product_name:'AC-DC Work and Commissioning Fee',         description:'N/A',                                                                                                                                   brand:'N/A',          model:'N/A', qty:1,   unit:'kWp',  unit_price:0},
      {product_category:'Service',      product_name:'Transport and Delivery',                   description:'N/A',                                                                                                                                   brand:'N/A',          model:'N/A', qty:1,   unit:'lot',  unit_price:0}
    ]
  };

  // ── IMPORT PART pre-filled rows (the "Import Part" table, from images 2-3) ──
  // Shown when "Imported Materials Included" is toggled ON.
  const defaultImportRows = {
    'On-Grid Solar System': [
      {item_head:'Inverter',                    specification:'On-grid solar inverter; complete with accessories.',                                                                                                                                        brand:'',      model:'',     qty:1,   unit:'Pcs',    fob_rate_usd:0},
      {item_head:'PV Panel',                    specification:'Mono-crystalline N-type bifacial PV modules; ≥590Wp; Efficiency ≥21%; Voltage ≥1500V DC; Aluminium frame; IP68 junction box; MC4 compatible; IEC 61215/61730 compliant; 30-year warranty.',brand:'',      model:'',     qty:1,   unit:'Pcs',    fob_rate_usd:0},
      {item_head:'PV Connector',                specification:'UV Protected, Male and Female.',                                                                                                                                                            brand:'N/A',   model:'N/A',  qty:1,   unit:'Set',    fob_rate_usd:0},
      {item_head:'Install Mounting Structure',  specification:'RCC Roof top steel structure',                                                                                                                                                             brand:'N/A',   model:'N/A',  qty:1,   unit:'Set',    fob_rate_usd:0},
      {item_head:'DC Cable',                    specification:'(PV cable) 4 sq.mm, (2 COIL) – 2 color (Red & Black) (As per site)',                                                                                                                      brand:'',      model:'4RM',  qty:1,   unit:'2 color',fob_rate_usd:0},
      {item_head:'Data Logger',                 specification:'Remote monitoring data logger; 4G/WiFi compatible.',                                                                                                                                        brand:'',      model:'',     qty:1,   unit:'lot',    fob_rate_usd:0},
      {item_head:'Weather Station',             specification:'Weather monitoring station.',                                                                                                                                                               brand:'Pv Met',model:'Pv Met',qty:1,  unit:'Set',    fob_rate_usd:0}
    ],
    'Off-Grid Solar System': [
      {item_head:'Inverter',                    specification:'Off-grid solar inverter; complete with accessories.',                                                                                                                                       brand:'',      model:'',     qty:1,   unit:'Pcs',    fob_rate_usd:0},
      {item_head:'BESS',                        specification:'Battery Energy Storage System; complete with BMS and accessories.',                                                                                                                         brand:'',      model:'',     qty:1,   unit:'Pcs',    fob_rate_usd:0},
      {item_head:'PV Panel',                    specification:'Mono-crystalline N-type bifacial PV modules; ≥590Wp; Efficiency ≥21%; Voltage ≥1500V DC; Aluminium frame; IP68 junction box; MC4 compatible; IEC 61215/61730 compliant; 30-year warranty.',brand:'',      model:'',     qty:1,   unit:'Pcs',    fob_rate_usd:0},
      {item_head:'PV Connector',                specification:'UV Protected, Male and Female.',                                                                                                                                                            brand:'N/A',   model:'N/A',  qty:1,   unit:'Set',    fob_rate_usd:0},
      {item_head:'Install Mounting Structure',  specification:'RCC Roof top steel structure',                                                                                                                                                             brand:'N/A',   model:'N/A',  qty:1,   unit:'Set',    fob_rate_usd:0},
      {item_head:'DC Cable',                    specification:'(PV cable) 4 sq.mm, (2 COIL) – 2 color (Red & Black) (As per site)',                                                                                                                      brand:'',      model:'4RM',  qty:1,   unit:'2 color',fob_rate_usd:0},
      {item_head:'Data Logger',                 specification:'Remote monitoring data logger; 4G/WiFi compatible.',                                                                                                                                        brand:'',      model:'',     qty:1,   unit:'lot',    fob_rate_usd:0},
      {item_head:'Weather Station',             specification:'Weather monitoring station.',                                                                                                                                                               brand:'Pv Met',model:'Pv Met',qty:1,  unit:'Set',    fob_rate_usd:0}
    ],
    'Hybrid Solar System': [
      {item_head:'Inverter',                    specification:'Hybrid solar inverter; 3-phase grid-tied; MPPT ≥2; Max DC ≥1100V; AC output 3-phase 400V, 50Hz; Efficiency ≥98%; THD <3%; PF adjustable; protections: anti-islanding, over/under voltage, surge; IP65; communication RS485/WiFi; IEC 62109 compliant; complete with accessories.',brand:'',model:'',qty:1,unit:'Pcs',fob_rate_usd:0},
      {item_head:'BESS',                        specification:'Battery Energy Storage System; complete with BMS and accessories.',                                                                                                                         brand:'',      model:'',     qty:1,   unit:'Pcs',    fob_rate_usd:0},
      {item_head:'Data Logger',                 specification:'Remote monitoring data logger; 4G/WiFi compatible.',                                                                                                                                        brand:'',      model:'',     qty:1,   unit:'lot',    fob_rate_usd:0},
      {item_head:'PV Panel',                    specification:'720Wp, N-type bifacial Double Glass Hi-efficiency Mono; Aluminium frame; IP68 junction box; MC4 compatible; IEC 61215/61730 compliant; 30-year warranty.',                                brand:'',      model:'',     qty:1,   unit:'Pcs',    fob_rate_usd:0},
      {item_head:'PV Connector',                specification:'UV Protected, Male and Female.',                                                                                                                                                            brand:'N/A',   model:'N/A',  qty:1,   unit:'Set',    fob_rate_usd:0},
      {item_head:'Install Mounting Structure',  specification:'RCC Roof top steel structure',                                                                                                                                                             brand:'N/A',   model:'N/A',  qty:1,   unit:'Set',    fob_rate_usd:0},
      {item_head:'DC Cable',                    specification:'(PV cable) 4 sq.mm, (2 COIL) – 2 color (Red & Black) (As per site)',                                                                                                                      brand:'',      model:'4RM',  qty:1,   unit:'2 color',fob_rate_usd:0},
      {item_head:'Weather Station',             specification:'Weather monitoring station.',                                                                                                                                                               brand:'Pv Met',model:'Pv Met',qty:1,  unit:'Set',    fob_rate_usd:0}
    ],
    'Solar Water Pumping System': [
      {item_head:'Pump Inverter / VFD',         specification:'Solar pump inverter/VFD; complete with accessories.',                                                                                                                                      brand:'',      model:'',     qty:1,   unit:'Pcs',    fob_rate_usd:0},
      {item_head:'PV Panel',                    specification:'Mono-crystalline PV modules; Aluminium frame; IP68 junction box; IEC compliant; 30-year performance warranty.',                                                                            brand:'',      model:'',     qty:1,   unit:'Pcs',    fob_rate_usd:0},
      {item_head:'PV Connector',                specification:'UV Protected, Male and Female.',                                                                                                                                                            brand:'N/A',   model:'N/A',  qty:1,   unit:'Set',    fob_rate_usd:0},
      {item_head:'Install Mounting Structure',  specification:'RCC Roof top steel structure',                                                                                                                                                             brand:'N/A',   model:'N/A',  qty:1,   unit:'Set',    fob_rate_usd:0},
      {item_head:'DC Cable',                    specification:'(PV cable) 4 sq.mm, (2 COIL) – 2 color (Red & Black) (As per site)',                                                                                                                      brand:'',      model:'4RM',  qty:1,   unit:'2 color',fob_rate_usd:0}
    ]
  };

  function initMethods(){
    const system = document.getElementById('systemType');
    const method = document.getElementById('calculationMethod');
    if(!system || !method) return;
    const current = method.dataset.current || document.querySelector('[name="calculation_method"]')?.value || '';
    const map = {
      'On-Grid Solar System':['Peak Load','Monthly Electricity Bill'],
      'Off-Grid Solar System':['Load Calculation','Monthly Electricity Bill'],
      'Hybrid Solar System':['Load Calculation','Monthly Electricity Bill'],
      'Solar Water Pumping System':['Water Pumping']
    };
    function render(){
      const old = method.value || current;
      method.innerHTML = '';
      (map[system.value] || []).forEach(v => {
        const o = document.createElement('option'); o.value = v; o.textContent = v; o.selected = old === v; method.appendChild(o);
      });
      updateBlocks();
    }
    system.addEventListener('change', render);
    method.addEventListener('change', updateBlocks);
    render();
  }

  function updateBlocks(){
    const method = document.getElementById('calculationMethod')?.value || '';
    document.querySelectorAll('.calc-block').forEach(b => b.style.display = b.dataset.method === method ? '' : 'none');
    const sys = document.getElementById('systemType')?.value || '';
    const sumSystem = document.getElementById('sumSystem');
    const sumMethod = document.getElementById('sumMethod');
    if(sumSystem) sumSystem.textContent = sys.replace(' Solar System','');
    if(sumMethod) sumMethod.textContent = method;
    fillDefaultProducts(sys);
    ensureImportRows(sys);
    calcAll();
  }

  function isBlankProductRow(tr){
    // A row is blank only when no product has been selected from the dropdown
    // AND the custom product name field is empty.
    // We deliberately ignore qty/unit/unit_price because PHP pre-fills
    // those with defaults (1 / pcs / 0) on a fresh empty row.
    const productSelect = tr.querySelector('.product-select');
    const productName   = tr.querySelector('.product-name');
    const noProductSelected = !productSelect || productSelect.selectedIndex === 0;
    const noNameEntered     = !productName   || String(productName.value).trim() === '';
    return noProductSelected && noNameEntered;
  }

  // Returns the correct local-material template depending on import mode
  function getProductDefaults(system){
    return isImportMode()
      ? (importedLocalPartRows[system] || [])
      : (defaultLocalOnlyRows[system] || []);
  }

  function fillProductTableWith(defaults){
    const tbody = document.querySelector('#productTable tbody');
    if(!tbody) return;
    const templateRow = tbody.querySelector('tr')?.cloneNode(true);
    if(!templateRow) return;
    tbody.innerHTML = '';
    defaults.forEach(item => {
      const tr = templateRow.cloneNode(true);
      // Clear all fields first
      tr.querySelectorAll('input').forEach(inp => {
        if(inp.type === 'hidden') inp.value = '1';
        else if(inp.type === 'number') inp.value = '0';
        else inp.value = '';
      });
      tr.querySelectorAll('select').forEach(s => s.selectedIndex = 0);
      // Fill with template data
      const categoryEl = tr.querySelector('.category'); if(categoryEl) categoryEl.value = item.product_category || '';
      const nameEl = tr.querySelector('.product-name'); if(nameEl) nameEl.value = item.product_name || '';
      const descriptionEl = tr.querySelector('.description'); if(descriptionEl){ const val = item.description || ''; descriptionEl.value = val; const trig = tr.querySelector('.desc-trigger'); if(trig){ trig.value = val; trig.title = val; trig.classList.toggle('has-value', val.length > 0); } }
      const brandEl = tr.querySelector('.brand'); if(brandEl) brandEl.value = item.brand || '';
      const modelEl = tr.querySelector('.model'); if(modelEl) modelEl.value = item.model || '';
      const qtyEl = tr.querySelector('.qty'); if(qtyEl) qtyEl.value = item.qty ?? 1;
      const unitEl = tr.querySelector('.unit'); if(unitEl) unitEl.value = item.unit || 'pcs';
      const priceEl = tr.querySelector('.unit-price'); if(priceEl) priceEl.value = item.unit_price ?? 0;
      const selectEl = tr.querySelector('.product-select'); if(selectEl) selectEl.selectedIndex = 0;
      const customFlag = tr.querySelector('.custom-flag'); if(customFlag) customFlag.value = '1';
      tr.dataset.custom = '1';
      tbody.appendChild(tr);
    });
    reindex('productTable','items');
  }

  // Track whether we have already done the first auto-fill this session.
  // After the initial fill, changing system-type will prompt the user before replacing.
  let _autoFilled = false;

  function fillDefaultProducts(system){
    const defaults = getProductDefaults(system);
    if(!Array.isArray(defaults) || !defaults.length) return;
    const tbody = document.querySelector('#productTable tbody');
    if(!tbody) return;

    const isNew = window.FQS_NEW_QUOTATION === true;

    if(!_autoFilled && isNew){
      // First-ever call on a new quotation — always fill (the PHP row is just a blank template)
      fillProductTableWith(defaults);
      _autoFilled = true;
      return;
    }

    // After the initial fill (or on edit quotations), only fill if the table
    // still has exactly one genuinely-blank row.
    const rows = Array.from(tbody.querySelectorAll('tr'));
    if(rows.length > 1 || rows.some(row => !isBlankProductRow(row))) return;
    fillProductTableWith(defaults);
  }

  // Called when user toggles "Imported Materials Included".
  // Replaces the local materials table with the matching template, asking first if there is data.
  function onImportToggle(){
    const sys = document.getElementById('systemType')?.value || '';
    const tbody = document.querySelector('#productTable tbody');
    if(tbody){
      const rows = Array.from(tbody.querySelectorAll('tr'));
      const allBlank = rows.length === 0 || rows.every(row => isBlankProductRow(row));
      if(!allBlank){
        const ok = confirm(
          'Switching the import mode will replace the current Local Materials list with the matching pre-filled template.\n\nYour current items will be lost. Continue?'
        );
        if(!ok){
          // Revert the checkbox back to its previous state
          const cb = document.getElementById('hasImportedMaterials');
          if(cb) cb.checked = !cb.checked;
          return;
        }
      }
    }
    // Wipe local table and refill with the new template
    const defaults = getProductDefaults(sys);
    if(defaults.length) fillProductTableWith(defaults);
    // Handle import table
    ensureImportRows(sys);
    // Update visibility and recalculate
    updateImportVisibility();
    calcAll();
  }

  function ensureImportRows(sys){
    const tbody = document.querySelector('#importTable tbody');
    if(!tbody || !isImportMode()) return;
    sys = sys || document.getElementById('systemType')?.value || '';
    const rows = Array.from(tbody.querySelectorAll('tr'));
    // Determine if the import table already has real data entered by the user
    const allBlank = rows.length === 0 || rows.every(tr =>
      Array.from(tr.querySelectorAll('input')).every(inp => {
        const v = String(inp.value).trim();
        return v === '' || v === '0' || v === '1';
      })
    );
    if(!allBlank) return; // Already has real data — don't overwrite

    const defaults = defaultImportRows[sys] || [];
    if(!defaults.length){
      if(rows.length === 0) cloneRow('importTable','import_items',false);
      return;
    }
    const templateRow = rows[0]?.cloneNode(true);
    if(!templateRow) return;
    tbody.innerHTML = '';
    defaults.forEach(item => {
      const tr = templateRow.cloneNode(true);
      // Clear all inputs
      tr.querySelectorAll('input').forEach(inp => {
        if(inp.type === 'number') inp.value = inp.classList.contains('import-qty') ? '1' : '0';
        else inp.value = '';
      });
      // Fill import item fields
      const headEl = tr.querySelector('[name*="[item_head]"]'); if(headEl) headEl.value = item.item_head || '';
      const specEl = tr.querySelector('[name*="[specification]"]'); if(specEl) specEl.value = item.specification || '';
      const brandEl = tr.querySelector('[name*="[brand]"]'); if(brandEl) brandEl.value = item.brand || '';
      const modelEl = tr.querySelector('[name*="[model]"]'); if(modelEl) modelEl.value = item.model || '';
      const qtyEl = tr.querySelector('.import-qty'); if(qtyEl) qtyEl.value = item.qty ?? 1;
      const unitEl = tr.querySelector('[name*="[unit]"]'); if(unitEl) unitEl.value = item.unit || 'pcs';
      const rateEl = tr.querySelector('.fob-rate'); if(rateEl) rateEl.value = item.fob_rate_usd ?? 0;
      const fobCell = tr.querySelector('.fob-total'); if(fobCell) fobCell.textContent = '0';
      tbody.appendChild(tr);
    });
    reindex('importTable','import_items');
  }

  function reindex(tableId, group){
    const rows = document.querySelectorAll(`#${tableId} tbody tr`);
    rows.forEach((tr,i)=>{
      const sl = tr.querySelector('.sl'); if(sl) sl.textContent = i+1;
      tr.querySelectorAll('input,select,textarea').forEach(el => {
        if(el.name) el.name = el.name.replace(new RegExp(`${group}\\[\\d+\\]`), `${group}[${i}]`);
      });
    });
  }

  function cloneRow(tableId, group, custom){
    const tbody = document.querySelector(`#${tableId} tbody`);
    if(!tbody || !tbody.rows.length) return;
    const tr = tbody.rows[tbody.rows.length-1].cloneNode(true);
    tr.querySelectorAll('input').forEach(i => {
      if(i.type === 'hidden') i.value = custom ? '1' : '0';
      else if(i.type === 'number') i.value = i.classList.contains('qty') ? '1' : '0';
      else i.value = '';
    });
    tr.querySelectorAll('select').forEach(s => s.selectedIndex = 0);
    tr.dataset.custom = custom ? '1' : '0';
    tbody.appendChild(tr); reindex(tableId, group); calcAll();
  }

  function fillProduct(tr, id){
    const p = products.find(x => String(x.id) === String(id));
    if(!p) return;
    tr.querySelector('.category').value = p.product_category;
    tr.querySelector('.product-name').value = p.product_name;
    tr.querySelector('.description').value = p.description || '';
    tr.querySelector('.brand').value = p.brand || '';
    tr.querySelector('.model').value = p.model || '';
    tr.querySelector('.unit').value = p.unit || 'pcs';
    tr.querySelector('.unit-price').value = p.unit_price || 0;
    tr.querySelector('.custom-flag').value = 0;
    calcAll();
  }

  function calcLoads(){
    let connected = 0, energy = 0;
    document.querySelectorAll('#loadTable tbody tr').forEach(tr => {
      const inputs = tr.querySelectorAll('.load-num');
      const qty = num(inputs[0]), watt = num(inputs[1]), backup = num(inputs[2]);
      const total = qty*watt, wh = total*backup;
      connected += total; energy += wh;
      tr.querySelector('.total-watt').textContent = money(total);
      tr.querySelector('.watt-hour').textContent = money(wh);
    });
    const sun = num(document.getElementById('sunHour')) || 4.5;
    const inv = connected*1.25, batteryWh = energy*1.25, battery = batterySpec(batteryWh, inv), panel = sun ? energy/sun*1.25 : 0;
    setText('connectedLoad', money(connected)+' W'); setText('energyNeed', money(energy)+' Wh'); setText('loadInverter', money(inv)+' VA'); setText('loadBattery', battery); setText('loadPanel', money(panel)+' W');
    if(document.getElementById('calculationMethod')?.value === 'Load Calculation'){
      setText('suggestInverter', money(inv)+' VA');
      setText('suggestBattery', document.getElementById('systemType')?.value === 'On-Grid Solar System' ? 'Not Required' : battery);
      setText('suggestPanel', money(panel)+' W');
    }
    return {capacityKw: panel/1000, inverterKw: inv/1000, battery};
  }

  function calcBill(){
    const bill = num(document.getElementById('monthlyBill')), rate = num(document.getElementById('electricityRate')), sun = num(document.getElementById('sunHour')) || 4.5;
    const monthly = rate ? bill/rate : 0, daily = monthly/30, solar = sun ? daily/sun : 0;
    setText('monthlyUnits', money(monthly)); setText('dailyUnits', money(daily)); setText('billSolar', money(solar)+' kW');
    if(document.getElementById('calculationMethod')?.value === 'Monthly Electricity Bill'){ setText('suggestInverter', money(solar)+' kW'); setText('suggestBattery', document.getElementById('systemType')?.value === 'On-Grid Solar System' ? 'Not Required' : 'As per backup requirement'); setText('suggestPanel', money(solar)+' kW'); }
    return {capacityKw: solar};
  }

  function calcPeak(){
    const peak = num(document.getElementById('peakLoad')), safety = num(document.getElementById('safetyFactor')) || 25, kw = peak*(1+safety/100);
    setText('peakInverter', money(kw)+' kW'); setText('peakPanel', money(kw)+' kW');
    if(document.getElementById('calculationMethod')?.value === 'Peak Load'){ setText('suggestInverter', money(kw)+' kW'); setText('suggestBattery','Not Required'); setText('suggestPanel', money(kw)+' kW'); }
    return {capacityKw: kw};
  }

  function calcPump(){
    const hp = num(document.getElementById('pumpHp')), kw = hp*.746;
    const headFt = num(document.getElementById('pumpHead')), headM = headFt*.3048;
    const waterLiters = num(document.getElementById('waterDemand')), dailyM3 = waterLiters/1000;
    const sun = num(document.getElementById('sunHour')) || 4.5;
    const pumpEff = num(document.getElementById('pumpEfficiency')) || .55;
    const systemEff = num(document.getElementById('systemEfficiency')) || .75;
    const hydraulicKwh = dailyM3*1000*9.81*headM/3600000;
    const electricalKwh = pumpEff ? hydraulicKwh/pumpEff : 0;
    const solarByWater = sun && systemEff ? electricalKwh/(sun*systemEff) : 0;
    const solarByHp = kw*1.5;
    const panel = roundSolarKw((Math.max(solarByWater, solarByHp) + solarByWater)*1.15);
    const type = document.getElementById('pumpType')?.value || 'AC';
    const inv = kw*(type === 'DC' ? 1.15 : 1.25);
    setText('pumpPower', money(kw)+' kW'); setText('pumpHeadView', money(headFt)+' ft'); setText('pumpDemandView', money(waterLiters)+' L/day'); setText('pumpEnergy', money(electricalKwh)+' kWh');
    setText('pumpPanel', money(panel)+' kW'); setText('pumpInverter', money(inv)+' kW');
    if(document.getElementById('calculationMethod')?.value === 'Water Pumping'){ setText('suggestInverter', money(inv)+' kW'); setText('suggestBattery','Not Required'); setText('suggestPanel', money(panel)+' kW'); }
    return {capacityKw: panel};
  }

  function calcItems(){
    let subtotal = 0;
    document.querySelectorAll('#productTable tbody tr').forEach(tr => {
      const total = num(tr.querySelector('.qty')) * num(tr.querySelector('.unit-price'));
      subtotal += total; tr.querySelector('.item-total').textContent = money(total);
    });
    const importMode = isImportMode();
    const ait = importMode ? subtotal * (num(document.getElementById('aitPercent'))/100) : 0;
    const vat = importMode ? (subtotal + ait) * (num(document.getElementById('vatPercent'))/100) : subtotal * (num(document.getElementById('vatPercent'))/100);
    const grand = Math.max(0, subtotal + ait + vat - (importMode ? 0 : num(document.getElementById('discountAmount'))));
    setText('subtotalView', money(subtotal)); setText('vatView', money(vat)); setText('grandView', money(grand)); setText('suggestCost', money(grand));
    setVal('subtotalInput', subtotal); setVal('vatAmountInput', vat); setVal('grandTotalInput', grand);
    return {subtotal, ait, vat, grand, localWithTax: subtotal + ait + vat};
  }

  function isImportMode(){ return !!document.getElementById('hasImportedMaterials')?.checked; }

  function updateImportVisibility(){
    const on = isImportMode();
    document.querySelectorAll('.import-section').forEach(section => section.style.display = on ? '' : 'none');
    if(on) ensureImportRows(document.getElementById('systemType')?.value);
    const vat = document.getElementById('vatPercent');
    if(on && vat && (vat.value === '' || Number(vat.value) === 0 || Number(vat.value) === 5)) vat.value = '7.5';
  }

  function calcImportRows(){
    let subtotalUsd = 0;
    document.querySelectorAll('#importTable tbody tr').forEach(tr => {
      const total = num(tr.querySelector('.import-qty')) * num(tr.querySelector('.fob-rate'));
      subtotalUsd += total;
      const cell = tr.querySelector('.fob-total'); if(cell) cell.textContent = money(total);
    });
    return subtotalUsd;
  }

  function calcImportCosting(local){
    updateImportVisibility();
    if(!isImportMode()) return {finalGrand: local.grand};
    const importSubtotal = calcImportRows();
    const lcFee = importSubtotal * (num(document.getElementById('lcFeePercent'))/100);
    const totalImportUsd = importSubtotal + lcFee + num(document.getElementById('freightUsd')) + num(document.getElementById('insuranceUsd')) + num(document.getElementById('otherImportCostUsd'));
    const totalImportBdt = totalImportUsd * (num(document.getElementById('dollarRate')) || 0);
    const totalExTax = totalImportBdt + local.subtotal;
    const totalWithTax = totalImportBdt + local.localWithTax;
    const margin = totalWithTax * (num(document.getElementById('marginPercent'))/100);
    const finalGrand = totalWithTax + margin;
    const dc = calcDcCapacity();
    const cpwEx = dc > 0 ? totalExTax/(dc*1000) : null;
    const cpwWith = dc > 0 ? totalWithTax/(dc*1000) : null;
    const cpkwEx = dc > 0 ? totalExTax/dc : null;
    const cpkwWith = dc > 0 ? totalWithTax/dc : null;

    setText('importSubtotalUsd', money(importSubtotal)); setText('lcFeeUsd', money(lcFee)); setText('totalImportUsd', money(totalImportUsd)); setText('totalImportBdt', money(totalImportBdt));
    setText('localSubtotalExTax', money(local.subtotal)); setText('aitAmount', money(local.ait)); setText('localVatPercentView', money(num(document.getElementById('vatPercent'))) + '%'); setText('localVatAmount', money(local.vat)); setText('localTotalWithTax', money(local.localWithTax));
    setText('finalImportBdt', money(totalImportBdt)); setText('finalLocalSubtotal', money(local.subtotal)); setText('finalAit', money(local.ait)); setText('finalVat', money(local.vat)); setText('finalLocalWithTax', money(local.localWithTax));
    setText('totalExcludingTax', money(totalExTax)); setText('totalIncludingTax', money(totalWithTax)); setText('marginAmount', money(margin)); setText('finalQuotationAmount', money(finalGrand));
    setText('cpwExTax', cpwEx === null ? 'N/A' : money(cpwEx) + ' BDT/W'); setText('cpwWithTax', cpwWith === null ? 'N/A' : money(cpwWith) + ' BDT/W');
    setText('cpkwExTax', cpkwEx === null ? 'N/A' : money(cpkwEx) + ' BDT/kW'); setText('cpkwWithTax', cpkwWith === null ? 'N/A' : money(cpkwWith) + ' BDT/kW');
    setText('grandView', money(finalGrand)); setText('suggestCost', money(finalGrand)); setVal('grandTotalInput', finalGrand);
    return {finalGrand};
  }

  function calcDcCapacity(){
    let auto = 0;
    document.querySelectorAll('#productTable tbody tr').forEach(tr => {
      const text = [
        tr.querySelector('.category')?.value,
        tr.querySelector('.product-name')?.value,
        tr.querySelector('.description')?.value,
        tr.querySelector('.model')?.value
      ].join(' ').toLowerCase();
      if(!text.includes('panel') && !text.includes('module')) return;
      const match = text.match(/(\d+(?:\.\d+)?)\s*w\b/i);
      if(match) auto += num(tr.querySelector('.qty')) * Number(match[1]) / 1000;
    });
    const dc = document.getElementById('dcCapacityKwp');
    if(dc && auto > 0 && (dc.value === '' || Number(dc.value) === 0 || dc.dataset.auto === '1')){
      dc.value = auto.toFixed(2);
      dc.dataset.auto = '1';
      return auto;
    }
    return num(dc);
  }

  function batterySpec(wh, inverterVa){
    if(!wh || wh <= 0) return 'Not Required';
    const voltage = inverterVa <= 1000 ? 12 : (inverterVa <= 3000 ? 24 : 48);
    const rawAh = wh/voltage;
    let ah = batterySizes.find(size => rawAh <= size);
    if(!ah) ah = Math.ceil(rawAh/50)*50;
    return `${voltage}V ${ah}Ah`;
  }
  function roundSolarKw(kw){
    if(!kw || kw <= 0) return 0;
    const step = kw <= 10 ? .5 : 1;
    return Math.ceil(kw/step)*step;
  }
  function calcEnergy(){
    const method = document.getElementById('calculationMethod')?.value || '';
    const load = calcLoads(), bill = calcBill(), peak = calcPeak(), pump = calcPump(), totals = calcItems();
    const project = calcImportCosting(totals);
    const capacityKw = method === 'Load Calculation' ? load.capacityKw : (method === 'Monthly Electricity Bill' ? bill.capacityKw : (method === 'Peak Load' ? peak.capacityKw : pump.capacityKw));
    const sun = num(document.getElementById('sunHour')) || 4.5, pr = num(document.getElementById('performanceRatio')) || .75, carbonFactor = num(document.getElementById('gridEmissionFactor')) || .62, coalFactor = num(document.getElementById('coalFactor')) || .4, rate = num(document.getElementById('electricityRate')) || 10;
    const annual = capacityKw*sun*365*pr, carbon = annual*carbonFactor, coal = annual*coalFactor;
    const savings = method === 'Monthly Electricity Bill' && num(document.getElementById('monthlyBill')) > 0 ? num(document.getElementById('monthlyBill'))*12 : annual*rate;
    setText('annualEnergy', money(annual)+' kWh/year'); setText('carbonReduced', money(carbon)+' kg CO2/year'); setText('coalReduced', money(coal)+' kg/year'); setText('paybackPeriod', savings > 0 ? money(project.finalGrand/savings)+' years' : 'N/A');
  }
  function setText(id, text){ const el = document.getElementById(id); if(el) el.textContent = text; }
  function setVal(id, value){ const el = document.getElementById(id); if(el) el.value = value.toFixed(2); }
  let calcTimer = null;
  function calcAll(){
    if(calcTimer) cancelAnimationFrame(calcTimer);
    calcTimer = requestAnimationFrame(() => {
      reindex('productTable','items');
      reindex('loadTable','loads');
      reindex('importTable','import_items');
      calcEnergy();
    });
  }

  document.addEventListener('input', e => {
    if(e.target.matches('#dcCapacityKwp')) e.target.dataset.auto = '0';
    if(e.target.matches('.load-num,.item-num,.import-num,.import-cost,#vatPercent,#discountAmount,.bill-calc,.peak-calc,.pump-calc,.energy-calc,#importTaxNote')) calcAll();
  });
  document.addEventListener('change', e => {
    if(e.target.matches('.product-select')) fillProduct(e.target.closest('tr'), e.target.value);
    if(e.target.matches('#hasImportedMaterials')) {
      onImportToggle();
      return;
    }
    if(e.target.matches('.pump-calc,#importTaxNoteChecked')) {
      if(e.target.matches('#importTaxNoteChecked')) setValText('importTaxNote', e.target.checked ? 'No VAT & AIT for Import Part' : '');
      calcAll();
    }
  });
  document.addEventListener('click', e => {
    const rem = e.target.closest('.remove-row');
    if(rem){ const tr = rem.closest('tr'), tbody = tr.parentElement; if(tbody.rows.length > 1) tr.remove(); calcAll(); }
    if(e.target.closest('#addLoad')) cloneRow('loadTable','loads',false);
    if(e.target.closest('#addProduct')) cloneRow('productTable','items',false);
    if(e.target.closest('#addCustom')) cloneRow('productTable','items',true);
    if(e.target.closest('#addImportItem')) cloneRow('importTable','import_items',false);
  });
  document.getElementById('quotationForm')?.addEventListener('submit', e => {
    const hasCustomer = document.getElementById('customerSelect')?.value || document.querySelector('[name="customer_name"]')?.value.trim();
    if(!hasCustomer){ e.preventDefault(); alert('Please select or enter customer information.'); return; }
    calcAll();
  });
  const chart = document.getElementById('monthlyChart');
  if(chart && window.Chart){ new Chart(chart,{type:'bar',data:{labels:JSON.parse(chart.dataset.labels||'[]'),datasets:[{label:'Monthly quotation amount',data:JSON.parse(chart.dataset.values||'[]'),backgroundColor:'#0b7a34'}]},options:{plugins:{legend:{display:false}},scales:{y:{beginAtZero:true}}}}); }
  function setValText(id, value){ const el = document.getElementById(id); if(el) el.value = value; }
  initMethods(); calcAll();

  // ── Sidebar & Mobile Nav ───────────────────────────────────────────────────
  (function initSidebar() {
    const sidebar = document.getElementById('appSidebar');
    const toggleBtns = document.querySelectorAll('.sidebar-toggle');
    const overlay = document.getElementById('sidebarOverlay');
    if (!sidebar) return;

    // Load state from localStorage for desktop
    const isCollapsed = localStorage.getItem('sidebar-collapsed') === 'true';
    if (isCollapsed && window.innerWidth >= 768) {
        sidebar.classList.add('collapsed');
    }

    function toggleDesktop() {
      const collapsed = sidebar.classList.toggle('collapsed');
      localStorage.setItem('sidebar-collapsed', collapsed);
    }

    function toggleMobile() {
      sidebar.classList.toggle('show');
      if (overlay) overlay.classList.toggle('show');
    }

    function closeMobile() {
      sidebar.classList.remove('show');
      if (overlay) overlay.classList.remove('show');
    }

    toggleBtns.forEach(btn => {
      btn.addEventListener('click', () => {
        if (window.innerWidth < 768) toggleMobile();
        else toggleDesktop();
      });
    });

    if (overlay) overlay.addEventListener('click', closeMobile);

    // Initialize tooltips (for collapsed desktop sidebar)
    if (window.bootstrap && bootstrap.Tooltip) {
      const tooltipTriggerList = [].slice.call(sidebar.querySelectorAll('[data-bs-toggle="tooltip"]'));
      tooltipTriggerList.map(function (tooltipTriggerEl) {
        return new bootstrap.Tooltip(tooltipTriggerEl, { boundary: document.body, trigger: 'hover' });
      });
      // Hide tooltip on click to prevent it from sticking when navigating
      sidebar.querySelectorAll('a').forEach(a => {
        a.addEventListener('click', () => {
           const tip = bootstrap.Tooltip.getInstance(a);
           if(tip) tip.hide();
           if(window.innerWidth < 768) closeMobile();
        });
      });
    }
  })();

  // ── Description Modal (Bootstrap) ────────────────────────────────────────────
  // Clicking the small .desc-trigger readonly input opens a full Bootstrap modal
  // with a large textarea. Save writes the value back to the hidden input and
  // updates the visible trigger input text.
  (function initDescModal(){
    const modalEl   = document.getElementById('descModal');
    if(!modalEl || !window.bootstrap) return;
    const bsModal   = new bootstrap.Modal(modalEl);
    const textarea  = document.getElementById('descModalTextarea');
    const btnSave   = document.getElementById('descModalSave');
    const charCount = document.getElementById('descCharCount');
    let activeTd    = null; // the <td> that owns the trigger that was clicked

    // Update character counter
    textarea?.addEventListener('input', () => {
      const n = textarea.value.length;
      if(charCount) charCount.textContent = n + ' character' + (n !== 1 ? 's' : '');
    });

    // Open modal when any .desc-trigger is clicked (event delegation for dynamic rows)
    document.addEventListener('click', e => {
      const trigger = e.target.closest('.desc-trigger');
      if(!trigger) return;
      activeTd = trigger.closest('td');
      const hidden = activeTd?.querySelector('input.description');
      const val = hidden ? hidden.value : '';
      if(textarea){
        textarea.value = val;
        textarea.dispatchEvent(new Event('input')); // refresh char counter
      }
      bsModal.show();
      // Focus textarea after modal animation
      modalEl.addEventListener('shown.bs.modal', () => textarea?.focus(), { once: true });
    });

    // Save button — write value back to hidden input + trigger display
    function doSave(){
      if(!activeTd) return;
      const val     = textarea?.value ?? '';
      const hidden  = activeTd.querySelector('input.description');
      const trigger = activeTd.querySelector('.desc-trigger');
      if(hidden)  hidden.value  = val;
      if(trigger){
        trigger.value = val;
        trigger.title = val;
        trigger.classList.toggle('has-value', val.length > 0);
      }
      bsModal.hide();
      activeTd = null;
    }

    btnSave?.addEventListener('click', doSave);

    // Ctrl+Enter shortcut inside textarea
    textarea?.addEventListener('keydown', e => {
      if(e.key === 'Enter' && e.ctrlKey){ e.preventDefault(); doSave(); }
    });

    // Clean up activeTd when modal is fully hidden
    modalEl.addEventListener('hidden.bs.modal', () => { activeTd = null; });
  })();
})();
