mantenimento-app 2.3.0 β†’ 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/app.js CHANGED
@@ -4,7 +4,6 @@ const defaultExpenseItems = [
4
4
  { label: "πŸ›’ Cibo/Alimenti", help: "Spesa alimentare mensile imputabile al nucleo familiare." },
5
5
  { label: "πŸ‘• Abbigliamento", help: "Spese medie mensili per abbigliamento dei figli." },
6
6
  { label: "πŸ’³ Finanziamenti in corso (extra mutuo)", help: "Rate mensili di finanziamenti diversi dal mutuo." },
7
- { label: "πŸ’³ Finanziamenti in corso (extra mutuo)", help: "Rate mensili di finanziamenti diversi dal mutuo." },
8
7
  { label: "πŸš— Spese macchina", help: "Carburante, assicurazione, bollo, manutenzione ordinaria." },
9
8
  { label: "🏒 Amministrazione condominio", help: "Quote condominiali ordinarie e costi amministrativi ricorrenti." },
10
9
  { label: "πŸŽ’ Spese scolastiche/mensa", help: "Costi scolastici ricorrenti, mensa e contributi periodici." },
@@ -279,13 +278,11 @@ const defaultExpenseItems = [
279
278
  extraAnnHint2: "Quota annuale straordinaria stimata a carico di {spouse} (es. sanitarie non ricorrenti, scolastiche extra, attivitΓ  non ordinarie).",
280
279
  extraMonthlyEstimate: "Quota mensile stimata: {amount}",
281
280
  firstHomeBoxTitle: "🏑 Mutuo prima casa ceduta",
282
- firstHomeBoxNote: "Dichiara i benefici economici della prima casa assegnata: il modello considera sia il mutuo ceduto sia il valore locativo quando la casa e assegnata al collocatario.",
283
- firstHomeMortgageEnabledLabel: "Benefici prima casa dei coniugi",
284
- firstHomeMortgageEnabledHint: "Attiva per includere tra i benefici compensativi il mutuo ceduto e/o il valore locativo della casa assegnata.",
281
+ firstHomeBoxNote: "Dichiara se esiste un mutuo sulla prima casa dei coniugi ceduta a uno dei due: il modello considera il trasferimento implicito quando la casa e assegnata al collocatario.",
282
+ firstHomeMortgageEnabledLabel: "Mutuo su prima casa dei coniugi",
283
+ firstHomeMortgageEnabledHint: "Attiva per includere il mutuo della prima casa ceduta nei benefici compensativi.",
285
284
  firstHomeMortgageAmountLabel: "Rata mutuo mensile ({currency})",
286
285
  firstHomeMortgageAmountHint: "Importo mensile complessivo della rata del mutuo prima casa.",
287
- firstHomeRentalValueLabel: "Casa (valore locativo) ({currency})",
288
- firstHomeRentalValueHint: "Valore locativo mensile della casa assegnata, usato per valorizzare il beneficio economico implicito.",
289
286
  firstHomeAssignedToLabel: "Casa assegnata a",
290
287
  firstHomeAssignedToHint: "Seleziona il coniuge a cui e ceduta la prima casa.",
291
288
  firstHomeAssignedToNone: "Nessuna cessione",
@@ -297,7 +294,7 @@ const defaultExpenseItems = [
297
294
  calcNoTransferWithBenefits: "Nessun trasferimento monetario suggerito. Benefici gia allocati: {benefits}.",
298
295
  calcBenefitFamilyAllowance: "Assegno familiare INPS percepito da {spouse}",
299
296
  calcBenefitPrimaryHomeMortgage: "Quota mutuo prima casa ceduta al collocatario ({payer} -> {receiver})",
300
- calcBenefitPrimaryHomeAssignment: "Assegnazione casa familiare (valore locativo) ({payer} -> {receiver})",
297
+ calcBenefitPrimaryHomeAssignment: "Assegnazione casa familiare - valore locativo ({receiver})",
301
298
  pdfCompBenefitsSection: "Benefici compensativi gia allocati",
302
299
  pdfCompBenefitsItem: "Beneficio",
303
300
  pdfCompBenefitsAmount: "Valore {currency}/mese",
@@ -307,7 +304,6 @@ const defaultExpenseItems = [
307
304
  pdfPrimaryHomeNotDeclared: "Non dichiarato",
308
305
  pdfPrimaryHomeAssignedTo: "Assegnata a",
309
306
  pdfPrimaryHomeMonthlyAmount: "Rata mensile",
310
- pdfPrimaryHomeRentalValue: "Casa (valore locativo)",
311
307
  pdfPrimaryHomeSplit: "Ripartizione mutuo",
312
308
  pdfPrimaryHomeAppliedOnlyColl: "Considerato solo se casa ceduta al collocatario.",
313
309
  pdfExtraordinaryRow: "Spese straordinarie (quota mensile da annuo)",
@@ -641,13 +637,11 @@ const defaultExpenseItems = [
641
637
  extraAnnHint2: "Estimated yearly extraordinary share for {spouse} (e.g., non-recurring medical, extra school, non-ordinary activities).",
642
638
  extraMonthlyEstimate: "Estimated monthly share: {amount}",
643
639
  firstHomeBoxTitle: "🏑 Assigned primary home mortgage",
644
- firstHomeBoxNote: "Declare the economic benefits linked to the assigned primary home: the model counts both the transferred mortgage and the rental value when the home is assigned to the custodial parent.",
645
- firstHomeMortgageEnabledLabel: "Primary-home benefits",
646
- firstHomeMortgageEnabledHint: "Enable to include in compensative benefits the transferred mortgage and/or the rental value of the assigned home.",
640
+ firstHomeBoxNote: "Declare whether there is a mortgage on the spouses' primary home assigned to one spouse: the model counts the implicit transfer when the home is assigned to the custodial parent.",
641
+ firstHomeMortgageEnabledLabel: "Mortgage on spouses' primary home",
642
+ firstHomeMortgageEnabledHint: "Enable to include the assigned primary-home mortgage in compensative benefits.",
647
643
  firstHomeMortgageAmountLabel: "Monthly mortgage payment ({currency})",
648
644
  firstHomeMortgageAmountHint: "Total monthly amount of the primary-home mortgage payment.",
649
- firstHomeRentalValueLabel: "Home (rental value) ({currency})",
650
- firstHomeRentalValueHint: "Monthly rental value of the assigned home, used to quantify the implicit economic benefit.",
651
645
  firstHomeAssignedToLabel: "Home assigned to",
652
646
  firstHomeAssignedToHint: "Select which spouse receives assignment of the primary home.",
653
647
  firstHomeAssignedToNone: "No assignment",
@@ -659,7 +653,7 @@ const defaultExpenseItems = [
659
653
  calcNoTransferWithBenefits: "No monetary transfer suggested. Already allocated benefits: {benefits}.",
660
654
  calcBenefitFamilyAllowance: "INPS family allowance received by {spouse}",
661
655
  calcBenefitPrimaryHomeMortgage: "Primary-home mortgage share assigned to custodial parent ({payer} -> {receiver})",
662
- calcBenefitPrimaryHomeAssignment: "Assigned family home (rental value) ({payer} -> {receiver})",
656
+ calcBenefitPrimaryHomeAssignment: "Primary home assignment - rental value ({receiver})",
663
657
  pdfCompBenefitsSection: "Compensative benefits already allocated",
664
658
  pdfCompBenefitsItem: "Benefit",
665
659
  pdfCompBenefitsAmount: "Value {currency}/month",
@@ -669,7 +663,6 @@ const defaultExpenseItems = [
669
663
  pdfPrimaryHomeNotDeclared: "Not declared",
670
664
  pdfPrimaryHomeAssignedTo: "Assigned to",
671
665
  pdfPrimaryHomeMonthlyAmount: "Monthly payment",
672
- pdfPrimaryHomeRentalValue: "Home (rental value)",
673
666
  pdfPrimaryHomeSplit: "Mortgage split",
674
667
  pdfPrimaryHomeAppliedOnlyColl: "Counted only when the home is assigned to the custodial parent.",
675
668
  pdfExtraordinaryRow: "Extraordinary expenses (monthly share from yearly)",
@@ -1222,8 +1215,6 @@ const defaultExpenseItems = [
1222
1215
  const hintPrimaCasaMutuoEnabled = document.getElementById("hintPrimaCasaMutuoEnabled");
1223
1216
  const lblPrimaCasaMutuoImporto = document.getElementById("lblPrimaCasaMutuoImporto");
1224
1217
  const hintPrimaCasaMutuoImporto = document.getElementById("hintPrimaCasaMutuoImporto");
1225
- const lblPrimaCasaValoreLocativo = document.getElementById("lblPrimaCasaValoreLocativo");
1226
- const hintPrimaCasaValoreLocativo = document.getElementById("hintPrimaCasaValoreLocativo");
1227
1218
  const lblPrimaCasaAssegnataA = document.getElementById("lblPrimaCasaAssegnataA");
1228
1219
  const hintPrimaCasaAssegnataA = document.getElementById("hintPrimaCasaAssegnataA");
1229
1220
  const lblPrimaCasaMutuoPerc1 = document.getElementById("lblPrimaCasaMutuoPerc1");
@@ -1287,8 +1278,6 @@ const defaultExpenseItems = [
1287
1278
  if (hintPrimaCasaMutuoEnabled) hintPrimaCasaMutuoEnabled.title = tr("firstHomeMortgageEnabledHint");
1288
1279
  if (lblPrimaCasaMutuoImporto) lblPrimaCasaMutuoImporto.textContent = msg("firstHomeMortgageAmountLabel", { currency: currentCurrency });
1289
1280
  if (hintPrimaCasaMutuoImporto) hintPrimaCasaMutuoImporto.title = tr("firstHomeMortgageAmountHint");
1290
- if (lblPrimaCasaValoreLocativo) lblPrimaCasaValoreLocativo.textContent = msg("firstHomeRentalValueLabel", { currency: currentCurrency });
1291
- if (hintPrimaCasaValoreLocativo) hintPrimaCasaValoreLocativo.title = tr("firstHomeRentalValueHint");
1292
1281
  if (lblPrimaCasaAssegnataA) lblPrimaCasaAssegnataA.textContent = tr("firstHomeAssignedToLabel");
1293
1282
  if (hintPrimaCasaAssegnataA) hintPrimaCasaAssegnataA.title = tr("firstHomeAssignedToHint");
1294
1283
  if (lblPrimaCasaMutuoPerc1) lblPrimaCasaMutuoPerc1.textContent = msg("firstHomeSplitLabel", { spouse: c1n() });
@@ -3601,7 +3590,6 @@ const defaultExpenseItems = [
3601
3590
  aFam2: num("assegnoFam2"),
3602
3591
  primaCasaMutuoEnabled: firstHome.enabled ? 1 : 0,
3603
3592
  primaCasaMutuoImporto: firstHome.amount,
3604
- primaCasaValoreLocativo: firstHome.rentalValue,
3605
3593
  primaCasaAssegnataA: firstHome.assignedTo,
3606
3594
  primaCasaMutuoPerc1: firstHome.share1,
3607
3595
  straordAnn1: num("straordAnn1"),
@@ -3643,10 +3631,10 @@ const defaultExpenseItems = [
3643
3631
  const aFam2 = Number(payload.aFam2 || 0);
3644
3632
  const primaCasaMutuoEnabled = Number(payload.primaCasaMutuoEnabled || 0) > 0;
3645
3633
  const primaCasaMutuoImporto = Math.max(0, Number(payload.primaCasaMutuoImporto || 0));
3646
- const primaCasaValoreLocativo = Math.max(0, Number(payload.primaCasaValoreLocativo || 0));
3647
3634
  const primaCasaAssegnataA = (String(payload.primaCasaAssegnataA || "") === "1" || String(payload.primaCasaAssegnataA || "") === "2")
3648
3635
  ? String(payload.primaCasaAssegnataA)
3649
3636
  : "";
3637
+ const primaCasaValoreLocativo = Math.max(0, Number(payload.primaCasaValoreLocativo || 0));
3650
3638
  const rawMutuoPerc1 = payload.primaCasaMutuoPerc1 === undefined ? 50 : payload.primaCasaMutuoPerc1;
3651
3639
  const primaCasaMutuoPerc1 = Math.min(100, Math.max(0, Number(rawMutuoPerc1 || 0)));
3652
3640
  const primaCasaMutuoPerc2 = 100 - primaCasaMutuoPerc1;
@@ -3705,10 +3693,9 @@ const defaultExpenseItems = [
3705
3693
  const assegnoBaseDa1a2 = assegnoDa1a2;
3706
3694
  const assegnoBaseDa2a1 = assegnoDa2a1;
3707
3695
 
3708
- const primaCasaAssignmentConsidered = primaCasaMutuoEnabled
3696
+ const primaCasaConsidered = primaCasaMutuoEnabled && primaCasaMutuoImporto > 0
3709
3697
  && primaCasaAssegnataA !== ""
3710
3698
  && Number(primaCasaAssegnataA) === collocatario;
3711
- const primaCasaConsidered = primaCasaAssignmentConsidered && primaCasaMutuoImporto > 0;
3712
3699
  let primaCasaTransfer1to2 = 0;
3713
3700
  let primaCasaTransfer2to1 = 0;
3714
3701
  if (primaCasaConsidered) {
@@ -3719,27 +3706,15 @@ const defaultExpenseItems = [
3719
3706
  }
3720
3707
  }
3721
3708
 
3722
- const primaCasaLocativeConsidered = primaCasaAssignmentConsidered && primaCasaValoreLocativo > 0;
3723
- let primaCasaLocativeTransfer1to2 = 0;
3724
- let primaCasaLocativeTransfer2to1 = 0;
3725
- if (primaCasaLocativeConsidered) {
3726
- if (primaCasaAssegnataA === "1") {
3727
- primaCasaLocativeTransfer2to1 = primaCasaValoreLocativo;
3728
- } else if (primaCasaAssegnataA === "2") {
3729
- primaCasaLocativeTransfer1to2 = primaCasaValoreLocativo;
3730
- }
3731
- }
3732
-
3733
- assegnoDa1a2 = Math.max(0, assegnoDa1a2 - primaCasaTransfer1to2 - primaCasaLocativeTransfer1to2);
3734
- assegnoDa2a1 = Math.max(0, assegnoDa2a1 - primaCasaTransfer2to1 - primaCasaLocativeTransfer2to1);
3709
+ assegnoDa1a2 = Math.max(0, assegnoDa1a2 - primaCasaTransfer1to2);
3710
+ assegnoDa2a1 = Math.max(0, assegnoDa2a1 - primaCasaTransfer2to1);
3735
3711
 
3736
3712
  const compensativeBenefits = [];
3737
3713
  if (aFam1 > 0.005) compensativeBenefits.push({ type: "family", to: 1, amount: aFam1 });
3738
3714
  if (aFam2 > 0.005) compensativeBenefits.push({ type: "family", to: 2, amount: aFam2 });
3739
3715
  if (primaCasaTransfer1to2 > 0.005) compensativeBenefits.push({ type: "primary-home-mortgage", from: 1, to: 2, amount: primaCasaTransfer1to2 });
3740
3716
  if (primaCasaTransfer2to1 > 0.005) compensativeBenefits.push({ type: "primary-home-mortgage", from: 2, to: 1, amount: primaCasaTransfer2to1 });
3741
- if (primaCasaLocativeTransfer1to2 > 0.005) compensativeBenefits.push({ type: "primary-home-assignment", from: 1, to: 2, amount: primaCasaLocativeTransfer1to2 });
3742
- if (primaCasaLocativeTransfer2to1 > 0.005) compensativeBenefits.push({ type: "primary-home-assignment", from: 2, to: 1, amount: primaCasaLocativeTransfer2to1 });
3717
+ if (primaCasaValoreLocativo > 0.005 && primaCasaAssegnataA !== "") compensativeBenefits.push({ type: "primary-home-assignment", to: Number(primaCasaAssegnataA), amount: primaCasaValoreLocativo });
3743
3718
 
3744
3719
  const post1 = disp1 - assegnoDa1a2 + assegnoDa2a1;
3745
3720
  const post2 = disp2 - assegnoDa2a1 + assegnoDa1a2;
@@ -3795,10 +3770,9 @@ const defaultExpenseItems = [
3795
3770
  quotaDiretta1, quotaDiretta2,
3796
3771
  saldo1, saldo2,
3797
3772
  assegnoBaseDa1a2, assegnoBaseDa2a1,
3798
- primaCasaMutuoEnabled, primaCasaMutuoImporto, primaCasaValoreLocativo, primaCasaAssegnataA,
3773
+ primaCasaMutuoEnabled, primaCasaMutuoImporto, primaCasaAssegnataA, primaCasaValoreLocativo,
3799
3774
  primaCasaMutuoPerc1, primaCasaMutuoPerc2,
3800
- primaCasaAssignmentConsidered, primaCasaConsidered, primaCasaTransfer1to2, primaCasaTransfer2to1,
3801
- primaCasaLocativeConsidered, primaCasaLocativeTransfer1to2, primaCasaLocativeTransfer2to1,
3775
+ primaCasaConsidered, primaCasaTransfer1to2, primaCasaTransfer2to1,
3802
3776
  compensativeBenefits,
3803
3777
  assegnoDa1a2, assegnoDa2a1,
3804
3778
  post1, post2,
@@ -3900,18 +3874,16 @@ const defaultExpenseItems = [
3900
3874
  function getFirstHomeMortgageInput() {
3901
3875
  const enabled = !!document.getElementById("primaCasaMutuoEnabled")?.checked;
3902
3876
  const amount = Math.max(0, num("primaCasaMutuoImporto"));
3903
- const rentalValue = Math.max(0, num("primaCasaValoreLocativo"));
3904
3877
  const assignedToRaw = String(document.getElementById("primaCasaAssegnataA")?.value || "").trim();
3905
3878
  const assignedTo = (assignedToRaw === "1" || assignedToRaw === "2") ? assignedToRaw : "";
3906
3879
  const share1 = Math.min(100, Math.max(0, num("primaCasaMutuoPerc1")));
3907
3880
  const share2 = 100 - share1;
3908
- return { enabled, amount, rentalValue, assignedTo, share1, share2 };
3881
+ return { enabled, amount, assignedTo, share1, share2 };
3909
3882
  }
3910
3883
 
3911
3884
  function updateFirstHomeMortgageUi() {
3912
3885
  const enabledEl = document.getElementById("primaCasaMutuoEnabled");
3913
3886
  const amountEl = document.getElementById("primaCasaMutuoImporto");
3914
- const rentalValueEl = document.getElementById("primaCasaValoreLocativo");
3915
3887
  const assignedEl = document.getElementById("primaCasaAssegnataA");
3916
3888
  const shareEl = document.getElementById("primaCasaMutuoPerc1");
3917
3889
  const splitInfoEl = document.getElementById("primaCasaMutuoSplitInfo");
@@ -3927,7 +3899,6 @@ const defaultExpenseItems = [
3927
3899
 
3928
3900
  const isEnabled = !!enabledEl.checked;
3929
3901
  amountEl.disabled = !isEnabled;
3930
- if (rentalValueEl) rentalValueEl.disabled = !isEnabled;
3931
3902
  assignedEl.disabled = !isEnabled;
3932
3903
  shareEl.disabled = !isEnabled;
3933
3904
  if (splitWrapEl) splitWrapEl.classList.toggle("is-disabled", !isEnabled);
@@ -4645,29 +4616,6 @@ const defaultExpenseItems = [
4645
4616
  return `<span class="spieg-help-wrap"><button type="button" class="spieg-help-btn" aria-label="${tooltipLabel}">i</button><span class="spieg-help-tip">${safeText}</span></span>`;
4646
4617
  };
4647
4618
 
4648
- let benefitSectionHtml = "";
4649
- if (compBenefits.length) {
4650
- const rawBenefs = Array.isArray(m.compensativeBenefits)
4651
- ? m.compensativeBenefits.filter((r) => r && Number(r.amount || 0) > 0.005)
4652
- : [];
4653
- const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1", "primary-home-assignment": "\uD83C\uDFE0" };
4654
- const cardsHtml = compBenefits
4655
- .map((row, i) => {
4656
- const icon = (rawBenefs[i] && typeIcons[rawBenefs[i].type]) || "\u2726";
4657
- return `<li class="spieg-benefit-card"><span class="spieg-benefit-icon">${icon}</span><span class="spieg-benefit-label">${escapeHtml(row.label)}</span><strong class="spieg-benefit-amount">${eur(row.amount)}</strong></li>`;
4658
- })
4659
- .join("");
4660
- const total = compBenefits.reduce((s, r) => s + r.amount, 0);
4661
- const totalLabel = currentLang === "en" ? "Total allocated benefits" : "Totale benefici allocati";
4662
- benefitSectionHtml = `
4663
- <div class="spieg-benefits-section">
4664
- <div class="spieg-benefits-label">&#127873;&ensp;${escapeHtml(tr("calcCompBenefitsLabel"))}</div>
4665
- <ul class="spieg-benefits-cards">${cardsHtml}</ul>
4666
- <div class="spieg-benefits-total"><span>${escapeHtml(totalLabel)}</span><strong>${eur(total)}</strong></div>
4667
- </div>
4668
- `;
4669
- }
4670
-
4671
4619
  let resultHtml;
4672
4620
  let resultDetail;
4673
4621
  if (isAssegno1) {
@@ -4675,7 +4623,6 @@ const defaultExpenseItems = [
4675
4623
  <div class="spieg-result-flow">${n1} &rarr; ${n2}</div>
4676
4624
  <div class="spieg-result-formula">${n1}: ${eur(m.quotaTeorica1)} &minus; ${eur(m.quotaDiretta1)}</div>
4677
4625
  <div class="spieg-result-amount ok">${eur(m.assegnoDa1a2)}</div>
4678
- ${benefitSectionHtml}
4679
4626
  `;
4680
4627
  resultDetail = tr("spiegDetailResultTransfer");
4681
4628
  } else if (isAssegno2) {
@@ -4683,14 +4630,30 @@ const defaultExpenseItems = [
4683
4630
  <div class="spieg-result-flow">${n2} &rarr; ${n1}</div>
4684
4631
  <div class="spieg-result-formula">${n2}: ${eur(m.quotaTeorica2)} &minus; ${eur(m.quotaDiretta2)}</div>
4685
4632
  <div class="spieg-result-amount ok">${eur(m.assegnoDa2a1)}</div>
4686
- ${benefitSectionHtml}
4687
4633
  `;
4688
4634
  resultDetail = tr("spiegDetailResultTransfer");
4689
4635
  } else {
4690
- if (benefitSectionHtml) {
4636
+ const benefitRows = getCompensativeBenefitRows(m, c1n(), c2n());
4637
+ if (benefitRows.length) {
4638
+ const rawBenefs = Array.isArray(m.compensativeBenefits)
4639
+ ? m.compensativeBenefits.filter((r) => r && Number(r.amount || 0) > 0.005)
4640
+ : [];
4641
+ const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1" };
4642
+ const cardsHtml = benefitRows
4643
+ .map((row, i) => {
4644
+ const icon = (rawBenefs[i] && typeIcons[rawBenefs[i].type]) || "\u2726";
4645
+ return `<li class="spieg-benefit-card"><span class="spieg-benefit-icon">${icon}</span><span class="spieg-benefit-label">${escapeHtml(row.label)}</span><strong class="spieg-benefit-amount">${eur(row.amount)}</strong></li>`;
4646
+ })
4647
+ .join("");
4648
+ const total = benefitRows.reduce((s, r) => s + r.amount, 0);
4649
+ const totalLabel = currentLang === "en" ? "Total allocated benefits" : "Totale benefici allocati";
4691
4650
  resultHtml = `
4692
4651
  <div class="spieg-no-transfer-badge">&#9878;&#65039;&ensp;${escapeHtml(tr("calcNoTransferSuggested"))}</div>
4693
- ${benefitSectionHtml}
4652
+ <div class="spieg-benefits-section">
4653
+ <div class="spieg-benefits-label">&#127873;&ensp;${escapeHtml(tr("calcCompBenefitsLabel"))}</div>
4654
+ <ul class="spieg-benefits-cards">${cardsHtml}</ul>
4655
+ <div class="spieg-benefits-total"><span>${escapeHtml(totalLabel)}</span><strong>${eur(total)}</strong></div>
4656
+ </div>
4694
4657
  `;
4695
4658
  } else {
4696
4659
  resultHtml = `<div class="spieg-result-empty ok">${tr("calcNoTransferSuggested")}</div>`;
@@ -4775,9 +4738,8 @@ const defaultExpenseItems = [
4775
4738
  return { label: msg("calcBenefitPrimaryHomeMortgage", { payer, receiver }), amount };
4776
4739
  }
4777
4740
  if (row.type === "primary-home-assignment") {
4778
- const payer = Number(row.from) === 2 ? name2 : name1;
4779
4741
  const receiver = Number(row.to) === 2 ? name2 : name1;
4780
- return { label: msg("calcBenefitPrimaryHomeAssignment", { payer, receiver }), amount };
4742
+ return { label: msg("calcBenefitPrimaryHomeAssignment", { receiver }), amount };
4781
4743
  }
4782
4744
  return { label: tr("calcCompBenefitsLabel"), amount };
4783
4745
  });
@@ -4859,30 +4821,6 @@ const defaultExpenseItems = [
4859
4821
  ${m.incomeMode === "cu" ? `<br /><strong>${tr("calcIncomeBaseNote")}</strong> ${tr("cuNetNoteText")}` : ""}
4860
4822
  `;
4861
4823
 
4862
- const benefitRows = getCompensativeBenefitRows(m, c1n(), c2n());
4863
- let benefitCardsHtml = "";
4864
- if (benefitRows.length) {
4865
- const rawBenefs = Array.isArray(m.compensativeBenefits)
4866
- ? m.compensativeBenefits.filter((r) => r && Number(r.amount || 0) > 0.005)
4867
- : [];
4868
- const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1", "primary-home-assignment": "\uD83C\uDFE0" };
4869
- const cardsHtml = benefitRows
4870
- .map((row, i) => {
4871
- const icon = (rawBenefs[i] && typeIcons[rawBenefs[i].type]) || "\u2726";
4872
- return `<li class="spieg-benefit-card"><span class="spieg-benefit-icon">${icon}</span><span class="spieg-benefit-label">${escapeHtml(row.label)}</span><strong class="spieg-benefit-amount">${eur(row.amount)}</strong></li>`;
4873
- })
4874
- .join("");
4875
- const total = benefitRows.reduce((s, r) => s + r.amount, 0);
4876
- const totalLabel = currentLang === "en" ? "Total allocated benefits" : "Totale benefici allocati";
4877
- benefitCardsHtml = `
4878
- <div class="result-benefits-box">
4879
- <div class="spieg-benefits-label">&#127873;&ensp;${escapeHtml(tr("calcCompBenefitsLabel"))}</div>
4880
- <ul class="spieg-benefits-cards">${cardsHtml}</ul>
4881
- <div class="spieg-benefits-total"><span>${escapeHtml(totalLabel)}</span><strong>${eur(total)}</strong></div>
4882
- </div>
4883
- `;
4884
- }
4885
-
4886
4824
  let mainHtml;
4887
4825
  if (m.assegnoDa1a2 > 0.005) {
4888
4826
  const perChild = m.figli > 1 ? `<div class="result-transfer-child">${eur(m.assegnoDa1a2 / m.figli)}&thinsp;${escapeHtml(currentLang === "en" ? "per child" : "per figlio")}</div>` : "";
@@ -4894,7 +4832,6 @@ const defaultExpenseItems = [
4894
4832
  </div>
4895
4833
  <div class="result-transfer-value">${eur(m.assegnoDa1a2)}<span class="result-transfer-per">&thinsp;${escapeHtml(tr("pdfPerMonth"))}</span></div>
4896
4834
  ${perChild}
4897
- ${benefitCardsHtml}
4898
4835
  `;
4899
4836
  } else if (m.assegnoDa2a1 > 0.005) {
4900
4837
  const perChild = m.figli > 1 ? `<div class="result-transfer-child">${eur(m.assegnoDa2a1 / m.figli)}&thinsp;${escapeHtml(currentLang === "en" ? "per child" : "per figlio")}</div>` : "";
@@ -4906,9 +4843,31 @@ const defaultExpenseItems = [
4906
4843
  </div>
4907
4844
  <div class="result-transfer-value">${eur(m.assegnoDa2a1)}<span class="result-transfer-per">&thinsp;${escapeHtml(tr("pdfPerMonth"))}</span></div>
4908
4845
  ${perChild}
4909
- ${benefitCardsHtml}
4910
4846
  `;
4911
4847
  } else {
4848
+ const benefitRows = getCompensativeBenefitRows(m, c1n(), c2n());
4849
+ let benefitCardsHtml = "";
4850
+ if (benefitRows.length) {
4851
+ const rawBenefs = Array.isArray(m.compensativeBenefits)
4852
+ ? m.compensativeBenefits.filter((r) => r && Number(r.amount || 0) > 0.005)
4853
+ : [];
4854
+ const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1" };
4855
+ const cardsHtml = benefitRows
4856
+ .map((row, i) => {
4857
+ const icon = (rawBenefs[i] && typeIcons[rawBenefs[i].type]) || "\u2726";
4858
+ return `<li class="spieg-benefit-card"><span class="spieg-benefit-icon">${icon}</span><span class="spieg-benefit-label">${escapeHtml(row.label)}</span><strong class="spieg-benefit-amount">${eur(row.amount)}</strong></li>`;
4859
+ })
4860
+ .join("");
4861
+ const total = benefitRows.reduce((s, r) => s + r.amount, 0);
4862
+ const totalLabel = currentLang === "en" ? "Total allocated benefits" : "Totale benefici allocati";
4863
+ benefitCardsHtml = `
4864
+ <div class="result-benefits-box">
4865
+ <div class="spieg-benefits-label">&#127873;&ensp;${escapeHtml(tr("calcCompBenefitsLabel"))}</div>
4866
+ <ul class="spieg-benefits-cards">${cardsHtml}</ul>
4867
+ <div class="spieg-benefits-total"><span>${escapeHtml(totalLabel)}</span><strong>${eur(total)}</strong></div>
4868
+ </div>
4869
+ `;
4870
+ }
4912
4871
  mainHtml = `<div class="spieg-no-transfer-badge">&#9878;&#65039;&ensp;${escapeHtml(tr("calcNoTransferSuggested"))}</div>${benefitCardsHtml}`;
4913
4872
  }
4914
4873
  resultMain.innerHTML = mainHtml;
@@ -5142,49 +5101,40 @@ const defaultExpenseItems = [
5142
5101
  ? `
5143
5102
  <tr><td>${tr("pdfPrimaryHomeAssignedTo")}</td><td>${primaryHomeAssignedLabel}</td></tr>
5144
5103
  <tr><td>${tr("pdfPrimaryHomeMonthlyAmount")}</td><td>${eur(m.primaCasaMutuoImporto || 0)}</td></tr>
5145
- <tr><td>${tr("pdfPrimaryHomeRentalValue")}</td><td>${eur(m.primaCasaValoreLocativo || 0)}</td></tr>
5146
5104
  <tr><td>${tr("pdfPrimaryHomeSplit")}</td><td>${c1NameEsc} ${(m.primaCasaMutuoPerc1 || 0).toFixed(0)}% Β· ${c2NameEsc} ${(m.primaCasaMutuoPerc2 || 0).toFixed(0)}%</td></tr>
5147
5105
  <tr><td>${tr("pdfPrimaryHomeAppliedOnlyColl")}</td><td>${m.primaCasaConsidered ? "OK" : tr("pdfPrimaryHomeNotDeclared")}</td></tr>`
5148
5106
  : `<tr><td>${tr("pdfPrimaryHomeMortgage")}</td><td>${tr("pdfPrimaryHomeNotDeclared")}</td></tr>`;
5149
5107
 
5150
5108
  let explainResultHtml = `<div class="pdf-explain-result-empty">${tr("calcNoTransferSuggested")}</div>`;
5151
- let pdfBenefitSectionHtml = "";
5152
- if (compBenefits.length) {
5153
- const rawBenefs = Array.isArray(m.compensativeBenefits)
5154
- ? m.compensativeBenefits.filter((row) => row && Number(row.amount || 0) > 0.005)
5155
- : [];
5156
- const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1", "primary-home-assignment": "\uD83C\uDFE0" };
5157
- const cardsHtml = compBenefits.map((row, idx) => {
5158
- const icon = (rawBenefs[idx] && typeIcons[rawBenefs[idx].type]) || "\u2726";
5159
- return `<li class="pdf-explain-benefit-card"><span class="pdf-explain-benefit-icon">${icon}</span><span class="pdf-explain-benefit-label">${escapeHtml(row.label)}</span><strong class="pdf-explain-benefit-amount">${eur(row.amount)}</strong></li>`;
5160
- }).join("");
5161
- const benefitsTotal = compBenefits.reduce((sum, row) => sum + Number(row.amount || 0), 0);
5162
- pdfBenefitSectionHtml = `
5163
- <div class="pdf-explain-benefits-section">
5164
- <div class="pdf-explain-benefits-label">&#127873;&ensp;${escapeHtml(tr("calcCompBenefitsLabel"))}</div>
5165
- <ul class="pdf-explain-benefits-cards">${cardsHtml}</ul>
5166
- <div class="pdf-explain-benefits-total"><span>${escapeHtml(tr("pdfCompBenefitsTotal"))}</span><strong>${eur(benefitsTotal)}</strong></div>
5167
- </div>
5168
- `;
5169
- }
5170
5109
  if (m.assegnoDa1a2 > 0.005) {
5171
5110
  explainResultHtml = `
5172
5111
  <div class="pdf-explain-flow">${c1NameEsc} &rarr; ${c2NameEsc}</div>
5173
5112
  <div class="pdf-explain-formula">${c1NameEsc}: ${eur(m.quotaTeorica1)} &minus; ${eur(m.quotaDiretta1)}</div>
5174
5113
  <div class="pdf-explain-amount">${eur(m.assegnoDa1a2)}</div>
5175
- ${pdfBenefitSectionHtml}
5176
5114
  `;
5177
5115
  } else if (m.assegnoDa2a1 > 0.005) {
5178
5116
  explainResultHtml = `
5179
5117
  <div class="pdf-explain-flow">${c2NameEsc} &rarr; ${c1NameEsc}</div>
5180
5118
  <div class="pdf-explain-formula">${c2NameEsc}: ${eur(m.quotaTeorica2)} &minus; ${eur(m.quotaDiretta2)}</div>
5181
5119
  <div class="pdf-explain-amount">${eur(m.assegnoDa2a1)}</div>
5182
- ${pdfBenefitSectionHtml}
5183
5120
  `;
5184
5121
  } else if (compBenefits.length) {
5122
+ const rawBenefs = Array.isArray(m.compensativeBenefits)
5123
+ ? m.compensativeBenefits.filter((row) => row && Number(row.amount || 0) > 0.005)
5124
+ : [];
5125
+ const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1" };
5126
+ const cardsHtml = compBenefits.map((row, idx) => {
5127
+ const icon = (rawBenefs[idx] && typeIcons[rawBenefs[idx].type]) || "\u2726";
5128
+ return `<li class="pdf-explain-benefit-card"><span class="pdf-explain-benefit-icon">${icon}</span><span class="pdf-explain-benefit-label">${escapeHtml(row.label)}</span><strong class="pdf-explain-benefit-amount">${eur(row.amount)}</strong></li>`;
5129
+ }).join("");
5130
+ const benefitsTotal = compBenefits.reduce((sum, row) => sum + Number(row.amount || 0), 0);
5185
5131
  explainResultHtml = `
5186
5132
  <div class="pdf-explain-no-transfer-badge">&#9878;&#65039;&ensp;${escapeHtml(tr("calcNoTransferSuggested"))}</div>
5187
- ${pdfBenefitSectionHtml}
5133
+ <div class="pdf-explain-benefits-section">
5134
+ <div class="pdf-explain-benefits-label">&#127873;&ensp;${escapeHtml(tr("calcCompBenefitsLabel"))}</div>
5135
+ <ul class="pdf-explain-benefits-cards">${cardsHtml}</ul>
5136
+ <div class="pdf-explain-benefits-total"><span>${escapeHtml(tr("pdfCompBenefitsTotal"))}</span><strong>${eur(benefitsTotal)}</strong></div>
5137
+ </div>
5188
5138
  `;
5189
5139
  }
5190
5140
 
@@ -6058,7 +6008,6 @@ ${scenarioLab.length ? `
6058
6008
  assegnoFam2: num("assegnoFam2"),
6059
6009
  primaCasaMutuoEnabled: document.getElementById("primaCasaMutuoEnabled")?.checked ? 1 : 0,
6060
6010
  primaCasaMutuoImporto: num("primaCasaMutuoImporto"),
6061
- primaCasaValoreLocativo: num("primaCasaValoreLocativo"),
6062
6011
  primaCasaAssegnataA: String(document.getElementById("primaCasaAssegnataA")?.value || ""),
6063
6012
  primaCasaMutuoPerc1: num("primaCasaMutuoPerc1"),
6064
6013
  straordAnn1: num("straordAnn1"),
@@ -6456,7 +6405,7 @@ ${scenarioLab.length ? `
6456
6405
  syncPermanenza("perm1");
6457
6406
  } else if (e.target.id === "perm2") {
6458
6407
  syncPermanenza("perm2");
6459
- } else if (e.target.id === "primaCasaMutuoPerc1" || e.target.id === "primaCasaMutuoImporto" || e.target.id === "primaCasaValoreLocativo") {
6408
+ } else if (e.target.id === "primaCasaMutuoPerc1" || e.target.id === "primaCasaMutuoImporto") {
6460
6409
  updateFirstHomeMortgageUi();
6461
6410
  } else if (e.target.id === "reddito1" || e.target.id === "reddito2") {
6462
6411
  const activeMode = document.getElementById("incomeMode")?.value || "monthly";
@@ -4,7 +4,6 @@ const defaultExpenseItems = [
4
4
  { label: "πŸ›’ Cibo/Alimenti", help: "Spesa alimentare mensile imputabile al nucleo familiare." },
5
5
  { label: "πŸ‘• Abbigliamento", help: "Spese medie mensili per abbigliamento dei figli." },
6
6
  { label: "πŸ’³ Finanziamenti in corso (extra mutuo)", help: "Rate mensili di finanziamenti diversi dal mutuo." },
7
- { label: "πŸ’³ Finanziamenti in corso (extra mutuo)", help: "Rate mensili di finanziamenti diversi dal mutuo." },
8
7
  { label: "πŸš— Spese macchina", help: "Carburante, assicurazione, bollo, manutenzione ordinaria." },
9
8
  { label: "🏒 Amministrazione condominio", help: "Quote condominiali ordinarie e costi amministrativi ricorrenti." },
10
9
  { label: "πŸŽ’ Spese scolastiche/mensa", help: "Costi scolastici ricorrenti, mensa e contributi periodici." },
@@ -279,13 +278,11 @@ const defaultExpenseItems = [
279
278
  extraAnnHint2: "Quota annuale straordinaria stimata a carico di {spouse} (es. sanitarie non ricorrenti, scolastiche extra, attivitΓ  non ordinarie).",
280
279
  extraMonthlyEstimate: "Quota mensile stimata: {amount}",
281
280
  firstHomeBoxTitle: "🏑 Mutuo prima casa ceduta",
282
- firstHomeBoxNote: "Dichiara i benefici economici della prima casa assegnata: il modello considera sia il mutuo ceduto sia il valore locativo quando la casa e assegnata al collocatario.",
283
- firstHomeMortgageEnabledLabel: "Benefici prima casa dei coniugi",
284
- firstHomeMortgageEnabledHint: "Attiva per includere tra i benefici compensativi il mutuo ceduto e/o il valore locativo della casa assegnata.",
281
+ firstHomeBoxNote: "Dichiara se esiste un mutuo sulla prima casa dei coniugi ceduta a uno dei due: il modello considera il trasferimento implicito quando la casa e assegnata al collocatario.",
282
+ firstHomeMortgageEnabledLabel: "Mutuo su prima casa dei coniugi",
283
+ firstHomeMortgageEnabledHint: "Attiva per includere il mutuo della prima casa ceduta nei benefici compensativi.",
285
284
  firstHomeMortgageAmountLabel: "Rata mutuo mensile ({currency})",
286
285
  firstHomeMortgageAmountHint: "Importo mensile complessivo della rata del mutuo prima casa.",
287
- firstHomeRentalValueLabel: "Casa (valore locativo) ({currency})",
288
- firstHomeRentalValueHint: "Valore locativo mensile della casa assegnata, usato per valorizzare il beneficio economico implicito.",
289
286
  firstHomeAssignedToLabel: "Casa assegnata a",
290
287
  firstHomeAssignedToHint: "Seleziona il coniuge a cui e ceduta la prima casa.",
291
288
  firstHomeAssignedToNone: "Nessuna cessione",
@@ -297,7 +294,7 @@ const defaultExpenseItems = [
297
294
  calcNoTransferWithBenefits: "Nessun trasferimento monetario suggerito. Benefici gia allocati: {benefits}.",
298
295
  calcBenefitFamilyAllowance: "Assegno familiare INPS percepito da {spouse}",
299
296
  calcBenefitPrimaryHomeMortgage: "Quota mutuo prima casa ceduta al collocatario ({payer} -> {receiver})",
300
- calcBenefitPrimaryHomeAssignment: "Assegnazione casa familiare (valore locativo) ({payer} -> {receiver})",
297
+ calcBenefitPrimaryHomeAssignment: "Assegnazione casa familiare - valore locativo ({receiver})",
301
298
  pdfCompBenefitsSection: "Benefici compensativi gia allocati",
302
299
  pdfCompBenefitsItem: "Beneficio",
303
300
  pdfCompBenefitsAmount: "Valore {currency}/mese",
@@ -307,7 +304,6 @@ const defaultExpenseItems = [
307
304
  pdfPrimaryHomeNotDeclared: "Non dichiarato",
308
305
  pdfPrimaryHomeAssignedTo: "Assegnata a",
309
306
  pdfPrimaryHomeMonthlyAmount: "Rata mensile",
310
- pdfPrimaryHomeRentalValue: "Casa (valore locativo)",
311
307
  pdfPrimaryHomeSplit: "Ripartizione mutuo",
312
308
  pdfPrimaryHomeAppliedOnlyColl: "Considerato solo se casa ceduta al collocatario.",
313
309
  pdfExtraordinaryRow: "Spese straordinarie (quota mensile da annuo)",
@@ -641,13 +637,11 @@ const defaultExpenseItems = [
641
637
  extraAnnHint2: "Estimated yearly extraordinary share for {spouse} (e.g., non-recurring medical, extra school, non-ordinary activities).",
642
638
  extraMonthlyEstimate: "Estimated monthly share: {amount}",
643
639
  firstHomeBoxTitle: "🏑 Assigned primary home mortgage",
644
- firstHomeBoxNote: "Declare the economic benefits linked to the assigned primary home: the model counts both the transferred mortgage and the rental value when the home is assigned to the custodial parent.",
645
- firstHomeMortgageEnabledLabel: "Primary-home benefits",
646
- firstHomeMortgageEnabledHint: "Enable to include in compensative benefits the transferred mortgage and/or the rental value of the assigned home.",
640
+ firstHomeBoxNote: "Declare whether there is a mortgage on the spouses' primary home assigned to one spouse: the model counts the implicit transfer when the home is assigned to the custodial parent.",
641
+ firstHomeMortgageEnabledLabel: "Mortgage on spouses' primary home",
642
+ firstHomeMortgageEnabledHint: "Enable to include the assigned primary-home mortgage in compensative benefits.",
647
643
  firstHomeMortgageAmountLabel: "Monthly mortgage payment ({currency})",
648
644
  firstHomeMortgageAmountHint: "Total monthly amount of the primary-home mortgage payment.",
649
- firstHomeRentalValueLabel: "Home (rental value) ({currency})",
650
- firstHomeRentalValueHint: "Monthly rental value of the assigned home, used to quantify the implicit economic benefit.",
651
645
  firstHomeAssignedToLabel: "Home assigned to",
652
646
  firstHomeAssignedToHint: "Select which spouse receives assignment of the primary home.",
653
647
  firstHomeAssignedToNone: "No assignment",
@@ -659,7 +653,7 @@ const defaultExpenseItems = [
659
653
  calcNoTransferWithBenefits: "No monetary transfer suggested. Already allocated benefits: {benefits}.",
660
654
  calcBenefitFamilyAllowance: "INPS family allowance received by {spouse}",
661
655
  calcBenefitPrimaryHomeMortgage: "Primary-home mortgage share assigned to custodial parent ({payer} -> {receiver})",
662
- calcBenefitPrimaryHomeAssignment: "Assigned family home (rental value) ({payer} -> {receiver})",
656
+ calcBenefitPrimaryHomeAssignment: "Primary home assignment - rental value ({receiver})",
663
657
  pdfCompBenefitsSection: "Compensative benefits already allocated",
664
658
  pdfCompBenefitsItem: "Benefit",
665
659
  pdfCompBenefitsAmount: "Value {currency}/month",
@@ -669,7 +663,6 @@ const defaultExpenseItems = [
669
663
  pdfPrimaryHomeNotDeclared: "Not declared",
670
664
  pdfPrimaryHomeAssignedTo: "Assigned to",
671
665
  pdfPrimaryHomeMonthlyAmount: "Monthly payment",
672
- pdfPrimaryHomeRentalValue: "Home (rental value)",
673
666
  pdfPrimaryHomeSplit: "Mortgage split",
674
667
  pdfPrimaryHomeAppliedOnlyColl: "Counted only when the home is assigned to the custodial parent.",
675
668
  pdfExtraordinaryRow: "Extraordinary expenses (monthly share from yearly)",
@@ -1222,8 +1215,6 @@ const defaultExpenseItems = [
1222
1215
  const hintPrimaCasaMutuoEnabled = document.getElementById("hintPrimaCasaMutuoEnabled");
1223
1216
  const lblPrimaCasaMutuoImporto = document.getElementById("lblPrimaCasaMutuoImporto");
1224
1217
  const hintPrimaCasaMutuoImporto = document.getElementById("hintPrimaCasaMutuoImporto");
1225
- const lblPrimaCasaValoreLocativo = document.getElementById("lblPrimaCasaValoreLocativo");
1226
- const hintPrimaCasaValoreLocativo = document.getElementById("hintPrimaCasaValoreLocativo");
1227
1218
  const lblPrimaCasaAssegnataA = document.getElementById("lblPrimaCasaAssegnataA");
1228
1219
  const hintPrimaCasaAssegnataA = document.getElementById("hintPrimaCasaAssegnataA");
1229
1220
  const lblPrimaCasaMutuoPerc1 = document.getElementById("lblPrimaCasaMutuoPerc1");
@@ -1287,8 +1278,6 @@ const defaultExpenseItems = [
1287
1278
  if (hintPrimaCasaMutuoEnabled) hintPrimaCasaMutuoEnabled.title = tr("firstHomeMortgageEnabledHint");
1288
1279
  if (lblPrimaCasaMutuoImporto) lblPrimaCasaMutuoImporto.textContent = msg("firstHomeMortgageAmountLabel", { currency: currentCurrency });
1289
1280
  if (hintPrimaCasaMutuoImporto) hintPrimaCasaMutuoImporto.title = tr("firstHomeMortgageAmountHint");
1290
- if (lblPrimaCasaValoreLocativo) lblPrimaCasaValoreLocativo.textContent = msg("firstHomeRentalValueLabel", { currency: currentCurrency });
1291
- if (hintPrimaCasaValoreLocativo) hintPrimaCasaValoreLocativo.title = tr("firstHomeRentalValueHint");
1292
1281
  if (lblPrimaCasaAssegnataA) lblPrimaCasaAssegnataA.textContent = tr("firstHomeAssignedToLabel");
1293
1282
  if (hintPrimaCasaAssegnataA) hintPrimaCasaAssegnataA.title = tr("firstHomeAssignedToHint");
1294
1283
  if (lblPrimaCasaMutuoPerc1) lblPrimaCasaMutuoPerc1.textContent = msg("firstHomeSplitLabel", { spouse: c1n() });
@@ -3601,7 +3590,6 @@ const defaultExpenseItems = [
3601
3590
  aFam2: num("assegnoFam2"),
3602
3591
  primaCasaMutuoEnabled: firstHome.enabled ? 1 : 0,
3603
3592
  primaCasaMutuoImporto: firstHome.amount,
3604
- primaCasaValoreLocativo: firstHome.rentalValue,
3605
3593
  primaCasaAssegnataA: firstHome.assignedTo,
3606
3594
  primaCasaMutuoPerc1: firstHome.share1,
3607
3595
  straordAnn1: num("straordAnn1"),
@@ -3643,10 +3631,10 @@ const defaultExpenseItems = [
3643
3631
  const aFam2 = Number(payload.aFam2 || 0);
3644
3632
  const primaCasaMutuoEnabled = Number(payload.primaCasaMutuoEnabled || 0) > 0;
3645
3633
  const primaCasaMutuoImporto = Math.max(0, Number(payload.primaCasaMutuoImporto || 0));
3646
- const primaCasaValoreLocativo = Math.max(0, Number(payload.primaCasaValoreLocativo || 0));
3647
3634
  const primaCasaAssegnataA = (String(payload.primaCasaAssegnataA || "") === "1" || String(payload.primaCasaAssegnataA || "") === "2")
3648
3635
  ? String(payload.primaCasaAssegnataA)
3649
3636
  : "";
3637
+ const primaCasaValoreLocativo = Math.max(0, Number(payload.primaCasaValoreLocativo || 0));
3650
3638
  const rawMutuoPerc1 = payload.primaCasaMutuoPerc1 === undefined ? 50 : payload.primaCasaMutuoPerc1;
3651
3639
  const primaCasaMutuoPerc1 = Math.min(100, Math.max(0, Number(rawMutuoPerc1 || 0)));
3652
3640
  const primaCasaMutuoPerc2 = 100 - primaCasaMutuoPerc1;
@@ -3705,10 +3693,9 @@ const defaultExpenseItems = [
3705
3693
  const assegnoBaseDa1a2 = assegnoDa1a2;
3706
3694
  const assegnoBaseDa2a1 = assegnoDa2a1;
3707
3695
 
3708
- const primaCasaAssignmentConsidered = primaCasaMutuoEnabled
3696
+ const primaCasaConsidered = primaCasaMutuoEnabled && primaCasaMutuoImporto > 0
3709
3697
  && primaCasaAssegnataA !== ""
3710
3698
  && Number(primaCasaAssegnataA) === collocatario;
3711
- const primaCasaConsidered = primaCasaAssignmentConsidered && primaCasaMutuoImporto > 0;
3712
3699
  let primaCasaTransfer1to2 = 0;
3713
3700
  let primaCasaTransfer2to1 = 0;
3714
3701
  if (primaCasaConsidered) {
@@ -3719,27 +3706,15 @@ const defaultExpenseItems = [
3719
3706
  }
3720
3707
  }
3721
3708
 
3722
- const primaCasaLocativeConsidered = primaCasaAssignmentConsidered && primaCasaValoreLocativo > 0;
3723
- let primaCasaLocativeTransfer1to2 = 0;
3724
- let primaCasaLocativeTransfer2to1 = 0;
3725
- if (primaCasaLocativeConsidered) {
3726
- if (primaCasaAssegnataA === "1") {
3727
- primaCasaLocativeTransfer2to1 = primaCasaValoreLocativo;
3728
- } else if (primaCasaAssegnataA === "2") {
3729
- primaCasaLocativeTransfer1to2 = primaCasaValoreLocativo;
3730
- }
3731
- }
3732
-
3733
- assegnoDa1a2 = Math.max(0, assegnoDa1a2 - primaCasaTransfer1to2 - primaCasaLocativeTransfer1to2);
3734
- assegnoDa2a1 = Math.max(0, assegnoDa2a1 - primaCasaTransfer2to1 - primaCasaLocativeTransfer2to1);
3709
+ assegnoDa1a2 = Math.max(0, assegnoDa1a2 - primaCasaTransfer1to2);
3710
+ assegnoDa2a1 = Math.max(0, assegnoDa2a1 - primaCasaTransfer2to1);
3735
3711
 
3736
3712
  const compensativeBenefits = [];
3737
3713
  if (aFam1 > 0.005) compensativeBenefits.push({ type: "family", to: 1, amount: aFam1 });
3738
3714
  if (aFam2 > 0.005) compensativeBenefits.push({ type: "family", to: 2, amount: aFam2 });
3739
3715
  if (primaCasaTransfer1to2 > 0.005) compensativeBenefits.push({ type: "primary-home-mortgage", from: 1, to: 2, amount: primaCasaTransfer1to2 });
3740
3716
  if (primaCasaTransfer2to1 > 0.005) compensativeBenefits.push({ type: "primary-home-mortgage", from: 2, to: 1, amount: primaCasaTransfer2to1 });
3741
- if (primaCasaLocativeTransfer1to2 > 0.005) compensativeBenefits.push({ type: "primary-home-assignment", from: 1, to: 2, amount: primaCasaLocativeTransfer1to2 });
3742
- if (primaCasaLocativeTransfer2to1 > 0.005) compensativeBenefits.push({ type: "primary-home-assignment", from: 2, to: 1, amount: primaCasaLocativeTransfer2to1 });
3717
+ if (primaCasaValoreLocativo > 0.005 && primaCasaAssegnataA !== "") compensativeBenefits.push({ type: "primary-home-assignment", to: Number(primaCasaAssegnataA), amount: primaCasaValoreLocativo });
3743
3718
 
3744
3719
  const post1 = disp1 - assegnoDa1a2 + assegnoDa2a1;
3745
3720
  const post2 = disp2 - assegnoDa2a1 + assegnoDa1a2;
@@ -3795,10 +3770,9 @@ const defaultExpenseItems = [
3795
3770
  quotaDiretta1, quotaDiretta2,
3796
3771
  saldo1, saldo2,
3797
3772
  assegnoBaseDa1a2, assegnoBaseDa2a1,
3798
- primaCasaMutuoEnabled, primaCasaMutuoImporto, primaCasaValoreLocativo, primaCasaAssegnataA,
3773
+ primaCasaMutuoEnabled, primaCasaMutuoImporto, primaCasaAssegnataA, primaCasaValoreLocativo,
3799
3774
  primaCasaMutuoPerc1, primaCasaMutuoPerc2,
3800
- primaCasaAssignmentConsidered, primaCasaConsidered, primaCasaTransfer1to2, primaCasaTransfer2to1,
3801
- primaCasaLocativeConsidered, primaCasaLocativeTransfer1to2, primaCasaLocativeTransfer2to1,
3775
+ primaCasaConsidered, primaCasaTransfer1to2, primaCasaTransfer2to1,
3802
3776
  compensativeBenefits,
3803
3777
  assegnoDa1a2, assegnoDa2a1,
3804
3778
  post1, post2,
@@ -3900,18 +3874,16 @@ const defaultExpenseItems = [
3900
3874
  function getFirstHomeMortgageInput() {
3901
3875
  const enabled = !!document.getElementById("primaCasaMutuoEnabled")?.checked;
3902
3876
  const amount = Math.max(0, num("primaCasaMutuoImporto"));
3903
- const rentalValue = Math.max(0, num("primaCasaValoreLocativo"));
3904
3877
  const assignedToRaw = String(document.getElementById("primaCasaAssegnataA")?.value || "").trim();
3905
3878
  const assignedTo = (assignedToRaw === "1" || assignedToRaw === "2") ? assignedToRaw : "";
3906
3879
  const share1 = Math.min(100, Math.max(0, num("primaCasaMutuoPerc1")));
3907
3880
  const share2 = 100 - share1;
3908
- return { enabled, amount, rentalValue, assignedTo, share1, share2 };
3881
+ return { enabled, amount, assignedTo, share1, share2 };
3909
3882
  }
3910
3883
 
3911
3884
  function updateFirstHomeMortgageUi() {
3912
3885
  const enabledEl = document.getElementById("primaCasaMutuoEnabled");
3913
3886
  const amountEl = document.getElementById("primaCasaMutuoImporto");
3914
- const rentalValueEl = document.getElementById("primaCasaValoreLocativo");
3915
3887
  const assignedEl = document.getElementById("primaCasaAssegnataA");
3916
3888
  const shareEl = document.getElementById("primaCasaMutuoPerc1");
3917
3889
  const splitInfoEl = document.getElementById("primaCasaMutuoSplitInfo");
@@ -3927,7 +3899,6 @@ const defaultExpenseItems = [
3927
3899
 
3928
3900
  const isEnabled = !!enabledEl.checked;
3929
3901
  amountEl.disabled = !isEnabled;
3930
- if (rentalValueEl) rentalValueEl.disabled = !isEnabled;
3931
3902
  assignedEl.disabled = !isEnabled;
3932
3903
  shareEl.disabled = !isEnabled;
3933
3904
  if (splitWrapEl) splitWrapEl.classList.toggle("is-disabled", !isEnabled);
@@ -4645,29 +4616,6 @@ const defaultExpenseItems = [
4645
4616
  return `<span class="spieg-help-wrap"><button type="button" class="spieg-help-btn" aria-label="${tooltipLabel}">i</button><span class="spieg-help-tip">${safeText}</span></span>`;
4646
4617
  };
4647
4618
 
4648
- let benefitSectionHtml = "";
4649
- if (compBenefits.length) {
4650
- const rawBenefs = Array.isArray(m.compensativeBenefits)
4651
- ? m.compensativeBenefits.filter((r) => r && Number(r.amount || 0) > 0.005)
4652
- : [];
4653
- const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1", "primary-home-assignment": "\uD83C\uDFE0" };
4654
- const cardsHtml = compBenefits
4655
- .map((row, i) => {
4656
- const icon = (rawBenefs[i] && typeIcons[rawBenefs[i].type]) || "\u2726";
4657
- return `<li class="spieg-benefit-card"><span class="spieg-benefit-icon">${icon}</span><span class="spieg-benefit-label">${escapeHtml(row.label)}</span><strong class="spieg-benefit-amount">${eur(row.amount)}</strong></li>`;
4658
- })
4659
- .join("");
4660
- const total = compBenefits.reduce((s, r) => s + r.amount, 0);
4661
- const totalLabel = currentLang === "en" ? "Total allocated benefits" : "Totale benefici allocati";
4662
- benefitSectionHtml = `
4663
- <div class="spieg-benefits-section">
4664
- <div class="spieg-benefits-label">&#127873;&ensp;${escapeHtml(tr("calcCompBenefitsLabel"))}</div>
4665
- <ul class="spieg-benefits-cards">${cardsHtml}</ul>
4666
- <div class="spieg-benefits-total"><span>${escapeHtml(totalLabel)}</span><strong>${eur(total)}</strong></div>
4667
- </div>
4668
- `;
4669
- }
4670
-
4671
4619
  let resultHtml;
4672
4620
  let resultDetail;
4673
4621
  if (isAssegno1) {
@@ -4675,7 +4623,6 @@ const defaultExpenseItems = [
4675
4623
  <div class="spieg-result-flow">${n1} &rarr; ${n2}</div>
4676
4624
  <div class="spieg-result-formula">${n1}: ${eur(m.quotaTeorica1)} &minus; ${eur(m.quotaDiretta1)}</div>
4677
4625
  <div class="spieg-result-amount ok">${eur(m.assegnoDa1a2)}</div>
4678
- ${benefitSectionHtml}
4679
4626
  `;
4680
4627
  resultDetail = tr("spiegDetailResultTransfer");
4681
4628
  } else if (isAssegno2) {
@@ -4683,14 +4630,30 @@ const defaultExpenseItems = [
4683
4630
  <div class="spieg-result-flow">${n2} &rarr; ${n1}</div>
4684
4631
  <div class="spieg-result-formula">${n2}: ${eur(m.quotaTeorica2)} &minus; ${eur(m.quotaDiretta2)}</div>
4685
4632
  <div class="spieg-result-amount ok">${eur(m.assegnoDa2a1)}</div>
4686
- ${benefitSectionHtml}
4687
4633
  `;
4688
4634
  resultDetail = tr("spiegDetailResultTransfer");
4689
4635
  } else {
4690
- if (benefitSectionHtml) {
4636
+ const benefitRows = getCompensativeBenefitRows(m, c1n(), c2n());
4637
+ if (benefitRows.length) {
4638
+ const rawBenefs = Array.isArray(m.compensativeBenefits)
4639
+ ? m.compensativeBenefits.filter((r) => r && Number(r.amount || 0) > 0.005)
4640
+ : [];
4641
+ const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1" };
4642
+ const cardsHtml = benefitRows
4643
+ .map((row, i) => {
4644
+ const icon = (rawBenefs[i] && typeIcons[rawBenefs[i].type]) || "\u2726";
4645
+ return `<li class="spieg-benefit-card"><span class="spieg-benefit-icon">${icon}</span><span class="spieg-benefit-label">${escapeHtml(row.label)}</span><strong class="spieg-benefit-amount">${eur(row.amount)}</strong></li>`;
4646
+ })
4647
+ .join("");
4648
+ const total = benefitRows.reduce((s, r) => s + r.amount, 0);
4649
+ const totalLabel = currentLang === "en" ? "Total allocated benefits" : "Totale benefici allocati";
4691
4650
  resultHtml = `
4692
4651
  <div class="spieg-no-transfer-badge">&#9878;&#65039;&ensp;${escapeHtml(tr("calcNoTransferSuggested"))}</div>
4693
- ${benefitSectionHtml}
4652
+ <div class="spieg-benefits-section">
4653
+ <div class="spieg-benefits-label">&#127873;&ensp;${escapeHtml(tr("calcCompBenefitsLabel"))}</div>
4654
+ <ul class="spieg-benefits-cards">${cardsHtml}</ul>
4655
+ <div class="spieg-benefits-total"><span>${escapeHtml(totalLabel)}</span><strong>${eur(total)}</strong></div>
4656
+ </div>
4694
4657
  `;
4695
4658
  } else {
4696
4659
  resultHtml = `<div class="spieg-result-empty ok">${tr("calcNoTransferSuggested")}</div>`;
@@ -4775,9 +4738,8 @@ const defaultExpenseItems = [
4775
4738
  return { label: msg("calcBenefitPrimaryHomeMortgage", { payer, receiver }), amount };
4776
4739
  }
4777
4740
  if (row.type === "primary-home-assignment") {
4778
- const payer = Number(row.from) === 2 ? name2 : name1;
4779
4741
  const receiver = Number(row.to) === 2 ? name2 : name1;
4780
- return { label: msg("calcBenefitPrimaryHomeAssignment", { payer, receiver }), amount };
4742
+ return { label: msg("calcBenefitPrimaryHomeAssignment", { receiver }), amount };
4781
4743
  }
4782
4744
  return { label: tr("calcCompBenefitsLabel"), amount };
4783
4745
  });
@@ -4859,30 +4821,6 @@ const defaultExpenseItems = [
4859
4821
  ${m.incomeMode === "cu" ? `<br /><strong>${tr("calcIncomeBaseNote")}</strong> ${tr("cuNetNoteText")}` : ""}
4860
4822
  `;
4861
4823
 
4862
- const benefitRows = getCompensativeBenefitRows(m, c1n(), c2n());
4863
- let benefitCardsHtml = "";
4864
- if (benefitRows.length) {
4865
- const rawBenefs = Array.isArray(m.compensativeBenefits)
4866
- ? m.compensativeBenefits.filter((r) => r && Number(r.amount || 0) > 0.005)
4867
- : [];
4868
- const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1", "primary-home-assignment": "\uD83C\uDFE0" };
4869
- const cardsHtml = benefitRows
4870
- .map((row, i) => {
4871
- const icon = (rawBenefs[i] && typeIcons[rawBenefs[i].type]) || "\u2726";
4872
- return `<li class="spieg-benefit-card"><span class="spieg-benefit-icon">${icon}</span><span class="spieg-benefit-label">${escapeHtml(row.label)}</span><strong class="spieg-benefit-amount">${eur(row.amount)}</strong></li>`;
4873
- })
4874
- .join("");
4875
- const total = benefitRows.reduce((s, r) => s + r.amount, 0);
4876
- const totalLabel = currentLang === "en" ? "Total allocated benefits" : "Totale benefici allocati";
4877
- benefitCardsHtml = `
4878
- <div class="result-benefits-box">
4879
- <div class="spieg-benefits-label">&#127873;&ensp;${escapeHtml(tr("calcCompBenefitsLabel"))}</div>
4880
- <ul class="spieg-benefits-cards">${cardsHtml}</ul>
4881
- <div class="spieg-benefits-total"><span>${escapeHtml(totalLabel)}</span><strong>${eur(total)}</strong></div>
4882
- </div>
4883
- `;
4884
- }
4885
-
4886
4824
  let mainHtml;
4887
4825
  if (m.assegnoDa1a2 > 0.005) {
4888
4826
  const perChild = m.figli > 1 ? `<div class="result-transfer-child">${eur(m.assegnoDa1a2 / m.figli)}&thinsp;${escapeHtml(currentLang === "en" ? "per child" : "per figlio")}</div>` : "";
@@ -4894,7 +4832,6 @@ const defaultExpenseItems = [
4894
4832
  </div>
4895
4833
  <div class="result-transfer-value">${eur(m.assegnoDa1a2)}<span class="result-transfer-per">&thinsp;${escapeHtml(tr("pdfPerMonth"))}</span></div>
4896
4834
  ${perChild}
4897
- ${benefitCardsHtml}
4898
4835
  `;
4899
4836
  } else if (m.assegnoDa2a1 > 0.005) {
4900
4837
  const perChild = m.figli > 1 ? `<div class="result-transfer-child">${eur(m.assegnoDa2a1 / m.figli)}&thinsp;${escapeHtml(currentLang === "en" ? "per child" : "per figlio")}</div>` : "";
@@ -4906,9 +4843,31 @@ const defaultExpenseItems = [
4906
4843
  </div>
4907
4844
  <div class="result-transfer-value">${eur(m.assegnoDa2a1)}<span class="result-transfer-per">&thinsp;${escapeHtml(tr("pdfPerMonth"))}</span></div>
4908
4845
  ${perChild}
4909
- ${benefitCardsHtml}
4910
4846
  `;
4911
4847
  } else {
4848
+ const benefitRows = getCompensativeBenefitRows(m, c1n(), c2n());
4849
+ let benefitCardsHtml = "";
4850
+ if (benefitRows.length) {
4851
+ const rawBenefs = Array.isArray(m.compensativeBenefits)
4852
+ ? m.compensativeBenefits.filter((r) => r && Number(r.amount || 0) > 0.005)
4853
+ : [];
4854
+ const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1" };
4855
+ const cardsHtml = benefitRows
4856
+ .map((row, i) => {
4857
+ const icon = (rawBenefs[i] && typeIcons[rawBenefs[i].type]) || "\u2726";
4858
+ return `<li class="spieg-benefit-card"><span class="spieg-benefit-icon">${icon}</span><span class="spieg-benefit-label">${escapeHtml(row.label)}</span><strong class="spieg-benefit-amount">${eur(row.amount)}</strong></li>`;
4859
+ })
4860
+ .join("");
4861
+ const total = benefitRows.reduce((s, r) => s + r.amount, 0);
4862
+ const totalLabel = currentLang === "en" ? "Total allocated benefits" : "Totale benefici allocati";
4863
+ benefitCardsHtml = `
4864
+ <div class="result-benefits-box">
4865
+ <div class="spieg-benefits-label">&#127873;&ensp;${escapeHtml(tr("calcCompBenefitsLabel"))}</div>
4866
+ <ul class="spieg-benefits-cards">${cardsHtml}</ul>
4867
+ <div class="spieg-benefits-total"><span>${escapeHtml(totalLabel)}</span><strong>${eur(total)}</strong></div>
4868
+ </div>
4869
+ `;
4870
+ }
4912
4871
  mainHtml = `<div class="spieg-no-transfer-badge">&#9878;&#65039;&ensp;${escapeHtml(tr("calcNoTransferSuggested"))}</div>${benefitCardsHtml}`;
4913
4872
  }
4914
4873
  resultMain.innerHTML = mainHtml;
@@ -5142,49 +5101,40 @@ const defaultExpenseItems = [
5142
5101
  ? `
5143
5102
  <tr><td>${tr("pdfPrimaryHomeAssignedTo")}</td><td>${primaryHomeAssignedLabel}</td></tr>
5144
5103
  <tr><td>${tr("pdfPrimaryHomeMonthlyAmount")}</td><td>${eur(m.primaCasaMutuoImporto || 0)}</td></tr>
5145
- <tr><td>${tr("pdfPrimaryHomeRentalValue")}</td><td>${eur(m.primaCasaValoreLocativo || 0)}</td></tr>
5146
5104
  <tr><td>${tr("pdfPrimaryHomeSplit")}</td><td>${c1NameEsc} ${(m.primaCasaMutuoPerc1 || 0).toFixed(0)}% Β· ${c2NameEsc} ${(m.primaCasaMutuoPerc2 || 0).toFixed(0)}%</td></tr>
5147
5105
  <tr><td>${tr("pdfPrimaryHomeAppliedOnlyColl")}</td><td>${m.primaCasaConsidered ? "OK" : tr("pdfPrimaryHomeNotDeclared")}</td></tr>`
5148
5106
  : `<tr><td>${tr("pdfPrimaryHomeMortgage")}</td><td>${tr("pdfPrimaryHomeNotDeclared")}</td></tr>`;
5149
5107
 
5150
5108
  let explainResultHtml = `<div class="pdf-explain-result-empty">${tr("calcNoTransferSuggested")}</div>`;
5151
- let pdfBenefitSectionHtml = "";
5152
- if (compBenefits.length) {
5153
- const rawBenefs = Array.isArray(m.compensativeBenefits)
5154
- ? m.compensativeBenefits.filter((row) => row && Number(row.amount || 0) > 0.005)
5155
- : [];
5156
- const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1", "primary-home-assignment": "\uD83C\uDFE0" };
5157
- const cardsHtml = compBenefits.map((row, idx) => {
5158
- const icon = (rawBenefs[idx] && typeIcons[rawBenefs[idx].type]) || "\u2726";
5159
- return `<li class="pdf-explain-benefit-card"><span class="pdf-explain-benefit-icon">${icon}</span><span class="pdf-explain-benefit-label">${escapeHtml(row.label)}</span><strong class="pdf-explain-benefit-amount">${eur(row.amount)}</strong></li>`;
5160
- }).join("");
5161
- const benefitsTotal = compBenefits.reduce((sum, row) => sum + Number(row.amount || 0), 0);
5162
- pdfBenefitSectionHtml = `
5163
- <div class="pdf-explain-benefits-section">
5164
- <div class="pdf-explain-benefits-label">&#127873;&ensp;${escapeHtml(tr("calcCompBenefitsLabel"))}</div>
5165
- <ul class="pdf-explain-benefits-cards">${cardsHtml}</ul>
5166
- <div class="pdf-explain-benefits-total"><span>${escapeHtml(tr("pdfCompBenefitsTotal"))}</span><strong>${eur(benefitsTotal)}</strong></div>
5167
- </div>
5168
- `;
5169
- }
5170
5109
  if (m.assegnoDa1a2 > 0.005) {
5171
5110
  explainResultHtml = `
5172
5111
  <div class="pdf-explain-flow">${c1NameEsc} &rarr; ${c2NameEsc}</div>
5173
5112
  <div class="pdf-explain-formula">${c1NameEsc}: ${eur(m.quotaTeorica1)} &minus; ${eur(m.quotaDiretta1)}</div>
5174
5113
  <div class="pdf-explain-amount">${eur(m.assegnoDa1a2)}</div>
5175
- ${pdfBenefitSectionHtml}
5176
5114
  `;
5177
5115
  } else if (m.assegnoDa2a1 > 0.005) {
5178
5116
  explainResultHtml = `
5179
5117
  <div class="pdf-explain-flow">${c2NameEsc} &rarr; ${c1NameEsc}</div>
5180
5118
  <div class="pdf-explain-formula">${c2NameEsc}: ${eur(m.quotaTeorica2)} &minus; ${eur(m.quotaDiretta2)}</div>
5181
5119
  <div class="pdf-explain-amount">${eur(m.assegnoDa2a1)}</div>
5182
- ${pdfBenefitSectionHtml}
5183
5120
  `;
5184
5121
  } else if (compBenefits.length) {
5122
+ const rawBenefs = Array.isArray(m.compensativeBenefits)
5123
+ ? m.compensativeBenefits.filter((row) => row && Number(row.amount || 0) > 0.005)
5124
+ : [];
5125
+ const typeIcons = { family: "\uD83C\uDFDB", "primary-home-mortgage": "\uD83C\uDFE1" };
5126
+ const cardsHtml = compBenefits.map((row, idx) => {
5127
+ const icon = (rawBenefs[idx] && typeIcons[rawBenefs[idx].type]) || "\u2726";
5128
+ return `<li class="pdf-explain-benefit-card"><span class="pdf-explain-benefit-icon">${icon}</span><span class="pdf-explain-benefit-label">${escapeHtml(row.label)}</span><strong class="pdf-explain-benefit-amount">${eur(row.amount)}</strong></li>`;
5129
+ }).join("");
5130
+ const benefitsTotal = compBenefits.reduce((sum, row) => sum + Number(row.amount || 0), 0);
5185
5131
  explainResultHtml = `
5186
5132
  <div class="pdf-explain-no-transfer-badge">&#9878;&#65039;&ensp;${escapeHtml(tr("calcNoTransferSuggested"))}</div>
5187
- ${pdfBenefitSectionHtml}
5133
+ <div class="pdf-explain-benefits-section">
5134
+ <div class="pdf-explain-benefits-label">&#127873;&ensp;${escapeHtml(tr("calcCompBenefitsLabel"))}</div>
5135
+ <ul class="pdf-explain-benefits-cards">${cardsHtml}</ul>
5136
+ <div class="pdf-explain-benefits-total"><span>${escapeHtml(tr("pdfCompBenefitsTotal"))}</span><strong>${eur(benefitsTotal)}</strong></div>
5137
+ </div>
5188
5138
  `;
5189
5139
  }
5190
5140
 
@@ -6058,7 +6008,6 @@ ${scenarioLab.length ? `
6058
6008
  assegnoFam2: num("assegnoFam2"),
6059
6009
  primaCasaMutuoEnabled: document.getElementById("primaCasaMutuoEnabled")?.checked ? 1 : 0,
6060
6010
  primaCasaMutuoImporto: num("primaCasaMutuoImporto"),
6061
- primaCasaValoreLocativo: num("primaCasaValoreLocativo"),
6062
6011
  primaCasaAssegnataA: String(document.getElementById("primaCasaAssegnataA")?.value || ""),
6063
6012
  primaCasaMutuoPerc1: num("primaCasaMutuoPerc1"),
6064
6013
  straordAnn1: num("straordAnn1"),
@@ -6456,7 +6405,7 @@ ${scenarioLab.length ? `
6456
6405
  syncPermanenza("perm1");
6457
6406
  } else if (e.target.id === "perm2") {
6458
6407
  syncPermanenza("perm2");
6459
- } else if (e.target.id === "primaCasaMutuoPerc1" || e.target.id === "primaCasaMutuoImporto" || e.target.id === "primaCasaValoreLocativo") {
6408
+ } else if (e.target.id === "primaCasaMutuoPerc1" || e.target.id === "primaCasaMutuoImporto") {
6460
6409
  updateFirstHomeMortgageUi();
6461
6410
  } else if (e.target.id === "reddito1" || e.target.id === "reddito2") {
6462
6411
  const activeMode = document.getElementById("incomeMode")?.value || "monthly";
@@ -358,12 +358,6 @@
358
358
  </label>
359
359
  <input id="primaCasaMutuoEnabled" type="checkbox" />
360
360
  </div>
361
- <div class="field">
362
- <label for="primaCasaMutuoImporto" class="label-row"><span id="lblPrimaCasaMutuoImporto">Rata mutuo mensile ({currency})</span>
363
- <span class="hint" id="hintPrimaCasaMutuoImporto" title="Importo mensile complessivo della rata del mutuo prima casa.">i</span>
364
- </label>
365
- <input id="primaCasaMutuoImporto" type="number" min="0" step="50" value="0" />
366
- </div>
367
361
  <div class="field" style="display: none;">
368
362
  <label for="primaCasaValoreLocativo" class="label-row"><span id="lblPrimaCasaValoreLocativo">Casa (valore locativo) ({currency})</span>
369
363
  <span class="hint" id="hintPrimaCasaValoreLocativo" title="Valore locativo mensile della casa assegnata, usato per valorizzare il beneficio economico implicito.">i</span>
@@ -380,7 +374,13 @@
380
374
  <option value="2">Coniuge 2</option>
381
375
  </select>
382
376
  </div>
383
- <div class="field" style="display: none;">
377
+ <div class="field">
378
+ <label for="primaCasaMutuoImporto" class="label-row"><span id="lblPrimaCasaMutuoImporto">Rata mutuo mensile ({currency})</span>
379
+ <span class="hint" id="hintPrimaCasaMutuoImporto" title="Importo mensile complessivo della rata del mutuo prima casa.">i</span>
380
+ </label>
381
+ <input id="primaCasaMutuoImporto" type="number" min="0" step="50" value="0" />
382
+ </div>
383
+ <div class="field">
384
384
  <div class="mortgage-split-slider" id="primaCasaMutuoSliderWrap">
385
385
  <div class="mortgage-split-side mortgage-split-side-left" id="primaCasaSplitLeft">
386
386
  <div class="mortgage-split-name" id="primaCasaSplitLeftName">Coniuge 1</div>
@@ -623,7 +623,7 @@
623
623
  <script src="supabase.min.js"></script>
624
624
  <script src="fabric.min.js"></script>
625
625
  <script src="html2pdf.bundle.min.js"></script>
626
- <script src="app.js?v=2.3.0"></script>
626
+ <script src="app.js?v=2.4.0"></script>
627
627
  </body>
628
628
  </html>
629
629
 
@@ -884,68 +884,138 @@
884
884
  color: #184a44;
885
885
  }
886
886
 
887
+ .extra-box-first-home {
888
+ background: linear-gradient(135deg, #ffffff 0%, #f0fffe 50%, #f5faff 100%);
889
+ border: 1px solid rgba(27, 141, 127, 0.15);
890
+ box-shadow: 0 2px 8px rgba(27, 141, 127, 0.08), inset 0 1px 0 rgba(255, 255, 255, 0.8);
891
+ }
892
+
893
+ .extra-box-first-home .extra-box-title::before {
894
+ content: '🏠 ';
895
+ margin-right: 4px;
896
+ }
897
+
887
898
  .extra-box-first-home .extra-grid {
888
899
  gap: 8px 10px;
889
900
  }
890
901
 
891
902
  .mortgage-split-slider {
892
- margin-top: 2px;
893
- border: 1px solid #b9d6cf;
894
- border-radius: 12px;
903
+ margin-top: 12px;
904
+ border: 1.5px solid rgba(27, 141, 127, 0.2);
905
+ border-radius: 16px;
895
906
  background:
896
- radial-gradient(120% 160% at 0% 0%, rgba(229, 247, 242, 0.8), transparent 58%),
897
- radial-gradient(120% 160% at 100% 0%, rgba(255, 241, 214, 0.8), transparent 58%),
898
- linear-gradient(180deg, #fafdfc, #eef7f5);
899
- padding: 8px;
907
+ radial-gradient(120% 160% at 0% 0%, rgba(229, 247, 242, 0.6), transparent 58%),
908
+ radial-gradient(120% 160% at 100% 0%, rgba(255, 241, 214, 0.6), transparent 58%),
909
+ linear-gradient(180deg, #fafffe, #f2f8f7);
910
+ padding: 14px;
900
911
  display: grid;
901
912
  grid-template-columns: minmax(0, 1fr) minmax(180px, 2fr) minmax(0, 1fr);
902
- gap: 6px;
913
+ gap: 10px;
903
914
  align-items: center;
904
- transition: opacity 0.2s ease;
915
+ box-shadow: 0 4px 12px rgba(27, 141, 127, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.6);
916
+ transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
917
+ }
918
+
919
+ .mortgage-split-slider:hover {
920
+ box-shadow: 0 8px 20px rgba(27, 141, 127, 0.15), inset 0 1px 0 rgba(255, 255, 255, 0.8);
921
+ border-color: rgba(27, 141, 127, 0.3);
905
922
  }
906
923
 
907
924
  .mortgage-split-slider.is-disabled {
908
- opacity: 0.58;
925
+ opacity: 0.55;
926
+ filter: grayscale(0.4);
909
927
  }
910
928
 
911
929
  .mortgage-split-side {
912
- border: 1px solid #c6ded8;
913
- border-radius: 12px;
914
- padding: 8px;
915
- background: linear-gradient(180deg, #ffffff, #f3faf8);
916
- min-height: 58px;
930
+ border: 1.5px solid rgba(27, 141, 127, 0.15);
931
+ border-radius: 14px;
932
+ padding: 12px;
933
+ background: linear-gradient(135deg, #ffffff 0%, #f5fbf9 100%);
934
+ min-height: 62px;
917
935
  display: grid;
918
936
  align-content: center;
919
- gap: 3px;
920
- box-shadow: 0 1px 3px rgba(17, 74, 68, 0.08);
937
+ gap: 4px;
938
+ box-shadow: 0 2px 6px rgba(27, 141, 127, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.7);
939
+ transition: all 0.28s cubic-bezier(0.34, 1.56, 0.64, 1);
940
+ position: relative;
941
+ overflow: hidden;
942
+ }
943
+
944
+ .mortgage-split-side::before {
945
+ content: '';
946
+ position: absolute;
947
+ top: 0;
948
+ left: 0;
949
+ right: 0;
950
+ bottom: 0;
951
+ background: radial-gradient(120% 200% at 50% 0%, rgba(255, 255, 255, 0.4), transparent 70%);
952
+ pointer-events: none;
953
+ opacity: 0;
954
+ transition: opacity 0.28s ease;
955
+ }
956
+
957
+ .mortgage-split-side:hover {
958
+ transform: translateY(-2px);
959
+ box-shadow: 0 6px 16px rgba(27, 141, 127, 0.12), inset 0 1px 2px rgba(255, 255, 255, 0.9);
960
+ border-color: rgba(27, 141, 127, 0.25);
961
+ }
962
+
963
+ .mortgage-split-side:hover::before {
964
+ opacity: 1;
921
965
  }
922
966
 
923
967
  .mortgage-split-side-left {
924
- box-shadow: inset 3px 0 0 #1b8d7f;
968
+ box-shadow: 0 2px 6px rgba(27, 141, 127, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.7), inset 3px 0 0 #1b8d7f;
969
+ background: linear-gradient(135deg, #effaf8 0%, #e5f5f1 100%);
970
+ }
971
+
972
+ .mortgage-split-side-left:hover {
973
+ box-shadow: 0 6px 16px rgba(27, 141, 127, 0.12), inset 0 1px 2px rgba(255, 255, 255, 0.9), inset 3px 0 0 #1b8d7f;
974
+ background: linear-gradient(135deg, #f0faf8 0%, #e8f7f4 100%);
925
975
  }
926
976
 
927
977
  .mortgage-split-side-right {
928
- box-shadow: inset -3px 0 0 #d89a35;
978
+ box-shadow: 0 2px 6px rgba(27, 141, 127, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.7), inset -3px 0 0 #d89a35;
929
979
  text-align: right;
980
+ background: linear-gradient(135deg, #fef9f1 0%, #fdf5e8 100%);
981
+ }
982
+
983
+ .mortgage-split-side-right:hover {
984
+ box-shadow: 0 6px 16px rgba(27, 141, 127, 0.12), inset 0 1px 2px rgba(255, 255, 255, 0.9), inset -3px 0 0 #d89a35;
985
+ background: linear-gradient(135deg, #fefaf4 0%, #fef7ed 100%);
930
986
  }
931
987
 
932
988
  .mortgage-split-name {
933
- font-size: 0.72rem;
989
+ font-size: 0.73rem;
934
990
  font-weight: 800;
935
- color: #2a4a46;
991
+ color: #1a3a36;
936
992
  overflow-wrap: anywhere;
993
+ letter-spacing: 0.3px;
994
+ text-shadow: 0 1px 2px rgba(255, 255, 255, 0.5);
937
995
  }
938
996
 
939
997
  .mortgage-split-amount {
940
- font-size: 0.9rem;
998
+ font-size: 0.95rem;
941
999
  font-weight: 900;
942
- color: #124f48;
943
- letter-spacing: 0.2px;
1000
+ color: #0b4440;
1001
+ letter-spacing: 0.3px;
1002
+ background: linear-gradient(135deg, #0f6659, #1b8d7f);
1003
+ -webkit-background-clip: text;
1004
+ -webkit-text-fill-color: transparent;
1005
+ background-clip: text;
1006
+ filter: drop-shadow(0 1px 2px rgba(27, 141, 127, 0.2));
1007
+ }
1008
+
1009
+ .mortgage-split-side-right .mortgage-split-amount {
1010
+ background: linear-gradient(135deg, #c86d28, #d89a35);
1011
+ -webkit-background-clip: text;
1012
+ -webkit-text-fill-color: transparent;
1013
+ background-clip: text;
944
1014
  }
945
1015
 
946
1016
  .mortgage-split-range-wrap {
947
1017
  position: relative;
948
- padding: 14px 0 6px;
1018
+ padding: 20px 0 8px;
949
1019
  --split-left: 50%;
950
1020
  }
951
1021
 
@@ -953,53 +1023,81 @@
953
1023
  -webkit-appearance: none;
954
1024
  appearance: none;
955
1025
  width: 100%;
956
- height: 8px;
1026
+ height: 10px;
957
1027
  border-radius: 999px;
958
1028
  background: linear-gradient(90deg,
959
- #2b9d8e 0%,
960
- #6cb9a9 var(--split-left),
961
- #dfb264 var(--split-left),
962
- #cb8a2d 100%);
1029
+ #16a396 0%,
1030
+ #3db5a0 20%,
1031
+ #6cbba8 var(--split-left),
1032
+ #ddb05a var(--split-left),
1033
+ #d89a35 80%,
1034
+ #c27f1d 100%);
963
1035
  outline: none;
964
1036
  margin: 0;
965
- transition: background 0.16s ease;
1037
+ transition: background 0.2s ease;
1038
+ box-shadow: 0 2px 4px rgba(22, 163, 150, 0.2), inset 0 1px 1px rgba(255, 255, 255, 0.3);
1039
+ }
1040
+
1041
+ .mortgage-split-range-wrap input[type="range"]:hover {
1042
+ box-shadow: 0 3px 8px rgba(22, 163, 150, 0.3), inset 0 1px 1px rgba(255, 255, 255, 0.4);
966
1043
  }
967
1044
 
968
1045
  .mortgage-split-range-wrap input[type="range"]::-webkit-slider-thumb {
969
1046
  -webkit-appearance: none;
970
1047
  appearance: none;
971
- width: 22px;
972
- height: 22px;
1048
+ width: 26px;
1049
+ height: 26px;
973
1050
  border-radius: 50%;
974
- border: 2px solid #ffffff;
975
- background: radial-gradient(circle at 35% 30%, #ffffff 0%, #e8f8f5 42%, #177a6f 100%);
976
- box-shadow: 0 3px 9px rgba(13, 70, 64, 0.35);
977
- cursor: pointer;
1051
+ border: 3px solid #ffffff;
1052
+ background: radial-gradient(circle at 30% 25%, #ffffff 0%, #f0faf8 30%, #16a396 100%);
1053
+ box-shadow: 0 4px 12px rgba(13, 70, 64, 0.4), 0 0 0 1px rgba(27, 141, 127, 0.15);
1054
+ cursor: grab;
1055
+ transition: all 0.2s ease;
1056
+ }
1057
+
1058
+ .mortgage-split-range-wrap input[type="range"]::-webkit-slider-thumb:hover {
1059
+ width: 28px;
1060
+ height: 28px;
1061
+ box-shadow: 0 6px 16px rgba(13, 70, 64, 0.5), 0 0 0 2px rgba(27, 141, 127, 0.2);
1062
+ }
1063
+
1064
+ .mortgage-split-range-wrap input[type="range"]::-webkit-slider-thumb:active {
1065
+ cursor: grabbing;
978
1066
  }
979
1067
 
980
1068
  .mortgage-split-range-wrap input[type="range"]::-moz-range-thumb {
981
- width: 22px;
982
- height: 22px;
1069
+ width: 26px;
1070
+ height: 26px;
983
1071
  border-radius: 50%;
984
- border: 2px solid #ffffff;
985
- background: radial-gradient(circle at 35% 30%, #ffffff 0%, #e8f8f5 42%, #177a6f 100%);
986
- box-shadow: 0 3px 9px rgba(13, 70, 64, 0.35);
987
- cursor: pointer;
1072
+ border: 3px solid #ffffff;
1073
+ background: radial-gradient(circle at 30% 25%, #ffffff 0%, #f0faf8 30%, #16a396 100%);
1074
+ box-shadow: 0 4px 12px rgba(13, 70, 64, 0.4), 0 0 0 1px rgba(27, 141, 127, 0.15);
1075
+ cursor: grab;
1076
+ transition: all 0.2s ease;
1077
+ }
1078
+
1079
+ .mortgage-split-range-wrap input[type="range"]::-moz-range-thumb:hover {
1080
+ width: 28px;
1081
+ height: 28px;
1082
+ box-shadow: 0 6px 16px rgba(13, 70, 64, 0.5), 0 0 0 2px rgba(27, 141, 127, 0.2);
988
1083
  }
989
1084
 
990
1085
  .mortgage-split-center {
991
1086
  position: absolute;
992
- top: -1px;
993
- left: 50%;
1087
+ top: 2px;
1088
+ left: var(--split-left);
994
1089
  transform: translateX(-50%);
995
- font-size: 0.7rem;
1090
+ font-size: 0.73rem;
996
1091
  font-weight: 900;
997
- color: #114c45;
998
- background: #ffffff;
999
- border: 1px solid #b8d5ce;
1092
+ color: #0f544d;
1093
+ background: linear-gradient(135deg, #ffffff, #f5fbf9);
1094
+ border: 1.5px solid rgba(27, 141, 127, 0.2);
1000
1095
  border-radius: 999px;
1001
- padding: 1px 7px;
1096
+ padding: 2px 9px;
1002
1097
  white-space: nowrap;
1098
+ box-shadow: 0 2px 6px rgba(27, 141, 127, 0.15), inset 0 1px 2px rgba(255, 255, 255, 0.6);
1099
+ transition: all 0.2s ease;
1100
+ letter-spacing: 0.2px;
1003
1101
  }
1004
1102
 
1005
1103
  #primaCasaMutuoSplitInfo {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mantenimento-app",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "description": "Frontend + backend architecture for the mantenimento calculator",
5
5
  "type": "commonjs",
6
6
  "main": "backend/calculate-model.js",