mantenimento-app 2.2.6 → 2.2.8

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
@@ -2800,6 +2800,8 @@ const defaultExpenseItems = [
2800
2800
  sliderBar.style.setProperty("--perm-left", `${p1}%`);
2801
2801
  sliderBar.setAttribute("aria-valuenow", String(p1));
2802
2802
  sliderBar.setAttribute("aria-valuetext", `${p1}% / ${p2}%`);
2803
+ const centerBadge = document.getElementById("permDaysCenter");
2804
+ if (centerBadge) centerBadge.textContent = `${p1}% / ${p2}%`;
2803
2805
  }
2804
2806
 
2805
2807
  // Update days bar below slider.
@@ -4675,24 +4677,42 @@ const defaultExpenseItems = [
4675
4677
  <strong class="sep-cost-value ${cls}">${formatted}</strong>
4676
4678
  </div>`;
4677
4679
  };
4680
+ const statHtml = (label, value, tone) => {
4681
+ const cls = lossClass(value);
4682
+ const formatted = value === null ? "&mdash;" : eur(value);
4683
+ return `<div class="sep-cost-stat ${tone || ""}">
4684
+ <span class="sep-cost-stat-label">${label}</span>
4685
+ <strong class="sep-cost-stat-value ${cls}">${formatted}</strong>
4686
+ </div>`;
4687
+ };
4688
+ const pillHtml = (label, value) => {
4689
+ const cls = lossClass(value);
4690
+ const formatted = value === null ? "&mdash;" : eur(value);
4691
+ return `<div class="sep-cost-pill">
4692
+ <span class="sep-cost-pill-label">${label}</span>
4693
+ <strong class="sep-cost-pill-value ${cls}">${formatted}</strong>
4694
+ </div>`;
4695
+ };
4678
4696
 
4679
4697
  panel.innerHTML = `
4680
4698
  <div class="sep-cost-panel">
4681
- <h3 class="sep-cost-title">${escapeHtml(tr("sepCostPanelTitle"))}</h3>
4682
- <div class="sep-cost-section">
4699
+ <h3 class="sep-cost-title"><span class="sep-cost-title-icon">&#128148;</span>${escapeHtml(tr("sepCostPanelTitle"))}</h3>
4700
+ <div class="sep-cost-hero">
4701
+ ${statHtml(tr("sepCostLossMonthly"), m.perditaMensile, "sep-cost-stat--primary")}
4702
+ ${statHtml(tr("sepCostLossAnnually"), m.perditaAnnua, "sep-cost-stat--secondary")}
4703
+ </div>
4704
+ <div class="sep-cost-section sep-cost-section--grid">
4683
4705
  ${rowHtml(tr("sepCostNetTogether"), m.nettoInsiemeCombinato, false)}
4684
4706
  ${rowHtml(tr("sepCostNetSeparated"), m.nettoSeparatoTotale, false)}
4685
- </div>
4686
- <div class="sep-cost-divider"></div>
4687
- <div class="sep-cost-section">
4688
4707
  ${m.separationAdjustmentHousingUtilities > 0
4689
4708
  ? rowHtml(tr("sepCostHousingUtilityAdj"), m.separationAdjustmentHousingUtilities, false)
4690
4709
  : ""}
4691
4710
  ${rowHtml(tr("sepCostDuplication"), m.costoSeparazioneMensile, false)}
4692
- ${rowHtml(tr("sepCostLossMonthly"), m.perditaMensile, true)}
4693
- ${rowHtml(tr("sepCostLossAnnually"), m.perditaAnnua, true)}
4694
- ${rowHtml(msg("sepCostLossSpouse", { spouse: c1NameEsc }), m.perditaSpouse1, false)}
4695
- ${rowHtml(msg("sepCostLossSpouse", { spouse: c2NameEsc }), m.perditaSpouse2, false)}
4711
+ </div>
4712
+ <div class="sep-cost-divider"></div>
4713
+ <div class="sep-cost-pill-wrap">
4714
+ ${pillHtml(msg("sepCostLossSpouse", { spouse: c1NameEsc }), m.perditaSpouse1)}
4715
+ ${pillHtml(msg("sepCostLossSpouse", { spouse: c2NameEsc }), m.perditaSpouse2)}
4696
4716
  </div>
4697
4717
  </div>
4698
4718
  `;
@@ -2800,6 +2800,8 @@ const defaultExpenseItems = [
2800
2800
  sliderBar.style.setProperty("--perm-left", `${p1}%`);
2801
2801
  sliderBar.setAttribute("aria-valuenow", String(p1));
2802
2802
  sliderBar.setAttribute("aria-valuetext", `${p1}% / ${p2}%`);
2803
+ const centerBadge = document.getElementById("permDaysCenter");
2804
+ if (centerBadge) centerBadge.textContent = `${p1}% / ${p2}%`;
2803
2805
  }
2804
2806
 
2805
2807
  // Update days bar below slider.
@@ -4675,24 +4677,42 @@ const defaultExpenseItems = [
4675
4677
  <strong class="sep-cost-value ${cls}">${formatted}</strong>
4676
4678
  </div>`;
4677
4679
  };
4680
+ const statHtml = (label, value, tone) => {
4681
+ const cls = lossClass(value);
4682
+ const formatted = value === null ? "&mdash;" : eur(value);
4683
+ return `<div class="sep-cost-stat ${tone || ""}">
4684
+ <span class="sep-cost-stat-label">${label}</span>
4685
+ <strong class="sep-cost-stat-value ${cls}">${formatted}</strong>
4686
+ </div>`;
4687
+ };
4688
+ const pillHtml = (label, value) => {
4689
+ const cls = lossClass(value);
4690
+ const formatted = value === null ? "&mdash;" : eur(value);
4691
+ return `<div class="sep-cost-pill">
4692
+ <span class="sep-cost-pill-label">${label}</span>
4693
+ <strong class="sep-cost-pill-value ${cls}">${formatted}</strong>
4694
+ </div>`;
4695
+ };
4678
4696
 
4679
4697
  panel.innerHTML = `
4680
4698
  <div class="sep-cost-panel">
4681
- <h3 class="sep-cost-title">${escapeHtml(tr("sepCostPanelTitle"))}</h3>
4682
- <div class="sep-cost-section">
4699
+ <h3 class="sep-cost-title"><span class="sep-cost-title-icon">&#128148;</span>${escapeHtml(tr("sepCostPanelTitle"))}</h3>
4700
+ <div class="sep-cost-hero">
4701
+ ${statHtml(tr("sepCostLossMonthly"), m.perditaMensile, "sep-cost-stat--primary")}
4702
+ ${statHtml(tr("sepCostLossAnnually"), m.perditaAnnua, "sep-cost-stat--secondary")}
4703
+ </div>
4704
+ <div class="sep-cost-section sep-cost-section--grid">
4683
4705
  ${rowHtml(tr("sepCostNetTogether"), m.nettoInsiemeCombinato, false)}
4684
4706
  ${rowHtml(tr("sepCostNetSeparated"), m.nettoSeparatoTotale, false)}
4685
- </div>
4686
- <div class="sep-cost-divider"></div>
4687
- <div class="sep-cost-section">
4688
4707
  ${m.separationAdjustmentHousingUtilities > 0
4689
4708
  ? rowHtml(tr("sepCostHousingUtilityAdj"), m.separationAdjustmentHousingUtilities, false)
4690
4709
  : ""}
4691
4710
  ${rowHtml(tr("sepCostDuplication"), m.costoSeparazioneMensile, false)}
4692
- ${rowHtml(tr("sepCostLossMonthly"), m.perditaMensile, true)}
4693
- ${rowHtml(tr("sepCostLossAnnually"), m.perditaAnnua, true)}
4694
- ${rowHtml(msg("sepCostLossSpouse", { spouse: c1NameEsc }), m.perditaSpouse1, false)}
4695
- ${rowHtml(msg("sepCostLossSpouse", { spouse: c2NameEsc }), m.perditaSpouse2, false)}
4711
+ </div>
4712
+ <div class="sep-cost-divider"></div>
4713
+ <div class="sep-cost-pill-wrap">
4714
+ ${pillHtml(msg("sepCostLossSpouse", { spouse: c1NameEsc }), m.perditaSpouse1)}
4715
+ ${pillHtml(msg("sepCostLossSpouse", { spouse: c2NameEsc }), m.perditaSpouse2)}
4696
4716
  </div>
4697
4717
  </div>
4698
4718
  `;
@@ -257,6 +257,7 @@
257
257
  <div class="perm-days-bar" id="permSliderBar" role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="40" aria-label="Permanenza figli presso Coniuge 1 (%)">
258
258
  <div class="perm-days-half perm-days-half--left" id="permDaysLeft" style="width:40%"><span class="perm-days-chip">12 gg</span></div>
259
259
  <div class="perm-days-half perm-days-half--right" id="permDaysRight" style="width:60%"><span class="perm-days-chip">18 gg</span></div>
260
+ <div class="perm-days-center" id="permDaysCenter">40% / 60%</div>
260
261
  <div class="perm-days-thumb" id="permDaysThumb" aria-hidden="true"></div>
261
262
  </div>
262
263
  <input id="perm2" type="number" min="0" max="100" step="1" value="60" aria-label="Permanenza figli presso Coniuge 2 (%)" />
@@ -599,7 +600,7 @@
599
600
  <script src="supabase.min.js"></script>
600
601
  <script src="fabric.min.js"></script>
601
602
  <script src="html2pdf.bundle.min.js"></script>
602
- <script src="app.js?v=2.2.6"></script>
603
+ <script src="app.js?v=2.2.8"></script>
603
604
  </body>
604
605
  </html>
605
606
 
@@ -571,6 +571,11 @@
571
571
  text-align: center;
572
572
  padding: 8px 6px;
573
573
  font-size: 0.9rem;
574
+ border-radius: 12px;
575
+ border-color: #bfd8d2;
576
+ background: linear-gradient(180deg, #ffffff, #f0f8f6);
577
+ font-weight: 800;
578
+ color: #114c45;
574
579
  }
575
580
 
576
581
  .perm-days-bar {
@@ -579,10 +584,14 @@
579
584
  border-radius: 17px;
580
585
  overflow: hidden;
581
586
  margin-top: 0;
582
- box-shadow: inset 0 1px 3px rgba(0,0,0,0.12), 0 2px 6px rgba(0,0,0,0.12);
587
+ box-shadow: inset 0 1px 2px rgba(12, 61, 56, 0.15), 0 2px 6px rgba(0, 0, 0, 0.1);
583
588
  position: relative;
584
589
  cursor: ew-resize;
585
- border: 1px solid #b8cac5;
590
+ border: 1px solid #b9d6cf;
591
+ background:
592
+ radial-gradient(120% 160% at 0% 0%, rgba(229, 247, 242, 0.8), transparent 58%),
593
+ radial-gradient(120% 160% at 100% 0%, rgba(255, 241, 214, 0.8), transparent 58%),
594
+ linear-gradient(180deg, #fafdfc, #eef7f5);
586
595
  user-select: none;
587
596
  touch-action: none;
588
597
  }
@@ -606,35 +615,59 @@
606
615
  align-items: center;
607
616
  justify-content: center;
608
617
  min-width: 74px;
609
- padding: 3px 10px;
618
+ padding: 2px 10px;
610
619
  border-radius: 999px;
611
- background: rgba(255, 255, 255, 0.78);
612
- border: 1px solid rgba(255, 255, 255, 0.95);
613
- box-shadow: 0 1px 4px rgba(0, 0, 0, 0.16);
620
+ background: rgba(255, 255, 255, 0.86);
621
+ border: 1px solid #c6ded8;
622
+ box-shadow: 0 1px 3px rgba(17, 74, 68, 0.12);
614
623
  line-height: 1;
624
+ font-size: 0.78rem;
625
+ font-weight: 900;
615
626
  }
616
627
 
617
628
  .perm-days-half--left {
618
- background: linear-gradient(90deg, #bfe9df, #6ec0b0);
629
+ background: linear-gradient(90deg, #2b9d8e, #6cb9a9);
630
+ justify-content: flex-start;
631
+ padding-left: 8px;
619
632
  }
620
633
 
621
634
  .perm-days-half--right {
622
- background: linear-gradient(90deg, #f2d8ab, #deaa59);
635
+ background: linear-gradient(90deg, #dfb264, #cb8a2d);
623
636
  color: #5d3d11;
637
+ justify-content: flex-end;
638
+ padding-right: 8px;
639
+ }
640
+
641
+ .perm-days-center {
642
+ position: absolute;
643
+ top: 50%;
644
+ left: 50%;
645
+ transform: translate(-50%, -50%);
646
+ font-size: 0.7rem;
647
+ font-weight: 900;
648
+ color: #114c45;
649
+ background: #ffffff;
650
+ border: 1px solid #b8d5ce;
651
+ border-radius: 999px;
652
+ padding: 1px 7px;
653
+ white-space: nowrap;
654
+ pointer-events: none;
655
+ z-index: 3;
624
656
  }
625
657
 
626
658
  .perm-days-thumb {
627
659
  position: absolute;
628
660
  top: 50%;
629
661
  left: var(--perm-left, 40%);
630
- width: 24px;
631
- height: 24px;
662
+ width: 22px;
663
+ height: 22px;
632
664
  border-radius: 50%;
633
665
  transform: translate(-50%, -50%);
634
- border: 3px solid #ffffff;
635
- background: #0f766d;
636
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.28);
666
+ border: 2px solid #ffffff;
667
+ background: radial-gradient(circle at 35% 30%, #ffffff 0%, #e8f8f5 42%, #177a6f 100%);
668
+ box-shadow: 0 3px 9px rgba(13, 70, 64, 0.35);
637
669
  pointer-events: none;
670
+ z-index: 4;
638
671
  }
639
672
 
640
673
  .perm-days-bar:focus-visible {
@@ -1847,19 +1880,78 @@
1847
1880
 
1848
1881
  .sep-cost-panel {
1849
1882
  margin-top: 10px;
1850
- border-radius: 14px;
1883
+ border-radius: 16px;
1851
1884
  border: 1.5px solid #e2a5a5;
1852
- background: linear-gradient(145deg, #fff5f3, #ffeceb 52%, #fff6f0);
1853
- box-shadow: 0 8px 22px rgba(130, 33, 33, 0.12);
1854
- padding: 12px;
1885
+ background:
1886
+ radial-gradient(120% 180% at 0% -20%, rgba(255, 241, 230, 0.75), transparent 58%),
1887
+ radial-gradient(120% 180% at 100% -20%, rgba(255, 228, 228, 0.72), transparent 56%),
1888
+ linear-gradient(145deg, #fff5f3, #ffeceb 52%, #fff6f0);
1889
+ box-shadow: 0 10px 24px rgba(130, 33, 33, 0.14);
1890
+ padding: 14px;
1855
1891
  }
1856
1892
 
1857
1893
  .sep-cost-title {
1858
- margin: 0 0 8px;
1859
- font-size: 0.98rem;
1894
+ margin: 0 0 10px;
1895
+ font-size: 1.01rem;
1860
1896
  font-weight: 900;
1861
1897
  color: #842d2d;
1862
1898
  letter-spacing: 0.2px;
1899
+ display: flex;
1900
+ align-items: center;
1901
+ gap: 8px;
1902
+ }
1903
+
1904
+ .sep-cost-title-icon {
1905
+ width: 24px;
1906
+ height: 24px;
1907
+ border-radius: 999px;
1908
+ background: rgba(140, 32, 32, 0.12);
1909
+ display: inline-flex;
1910
+ align-items: center;
1911
+ justify-content: center;
1912
+ font-size: 0.85rem;
1913
+ }
1914
+
1915
+ .sep-cost-hero {
1916
+ display: grid;
1917
+ grid-template-columns: repeat(2, minmax(0, 1fr));
1918
+ gap: 8px;
1919
+ margin-bottom: 9px;
1920
+ }
1921
+
1922
+ .sep-cost-stat {
1923
+ border-radius: 12px;
1924
+ border: 1px solid rgba(138, 44, 44, 0.16);
1925
+ background: rgba(255,255,255,0.82);
1926
+ padding: 8px 10px;
1927
+ display: grid;
1928
+ gap: 2px;
1929
+ min-width: 0;
1930
+ }
1931
+
1932
+ .sep-cost-stat--primary {
1933
+ background: linear-gradient(130deg, rgba(255, 233, 232, 0.95), rgba(255, 244, 232, 0.92));
1934
+ border-color: rgba(170, 67, 46, 0.35);
1935
+ }
1936
+
1937
+ .sep-cost-stat--secondary {
1938
+ background: linear-gradient(130deg, rgba(255, 245, 240, 0.95), rgba(255, 235, 231, 0.92));
1939
+ border-color: rgba(164, 61, 61, 0.28);
1940
+ }
1941
+
1942
+ .sep-cost-stat-label {
1943
+ font-size: 0.72rem;
1944
+ font-weight: 800;
1945
+ color: #7a3d3d;
1946
+ text-transform: uppercase;
1947
+ letter-spacing: 0.04em;
1948
+ }
1949
+
1950
+ .sep-cost-stat-value {
1951
+ font-size: 1.12rem;
1952
+ font-weight: 900;
1953
+ font-variant-numeric: tabular-nums;
1954
+ white-space: nowrap;
1863
1955
  }
1864
1956
 
1865
1957
  .sep-cost-section {
@@ -1867,6 +1959,10 @@
1867
1959
  gap: 7px;
1868
1960
  }
1869
1961
 
1962
+ .sep-cost-section--grid {
1963
+ grid-template-columns: repeat(2, minmax(0, 1fr));
1964
+ }
1965
+
1870
1966
  .sep-cost-divider {
1871
1967
  height: 1px;
1872
1968
  margin: 8px 0;
@@ -1893,6 +1989,7 @@
1893
1989
  font-size: 0.82rem;
1894
1990
  color: #6a3939;
1895
1991
  font-weight: 700;
1992
+ min-width: 0;
1896
1993
  }
1897
1994
 
1898
1995
  .sep-cost-value {
@@ -1903,6 +2000,47 @@
1903
2000
  color: #5d2e2e;
1904
2001
  }
1905
2002
 
2003
+ .sep-cost-pill-wrap {
2004
+ display: grid;
2005
+ grid-template-columns: repeat(2, minmax(0, 1fr));
2006
+ gap: 8px;
2007
+ }
2008
+
2009
+ .sep-cost-pill {
2010
+ border: 1px solid rgba(134, 40, 40, 0.18);
2011
+ border-radius: 11px;
2012
+ background: rgba(255,255,255,0.82);
2013
+ padding: 8px 10px;
2014
+ display: grid;
2015
+ gap: 2px;
2016
+ }
2017
+
2018
+ .sep-cost-pill-label {
2019
+ font-size: 0.76rem;
2020
+ color: #714343;
2021
+ font-weight: 700;
2022
+ line-height: 1.2;
2023
+ }
2024
+
2025
+ .sep-cost-pill-value {
2026
+ font-size: 1rem;
2027
+ font-weight: 900;
2028
+ font-variant-numeric: tabular-nums;
2029
+ white-space: nowrap;
2030
+ }
2031
+
2032
+ @media (max-width: 720px) {
2033
+ .sep-cost-hero,
2034
+ .sep-cost-section--grid,
2035
+ .sep-cost-pill-wrap {
2036
+ grid-template-columns: 1fr;
2037
+ }
2038
+ .sep-cost-stat-value,
2039
+ .sep-cost-pill-value {
2040
+ white-space: normal;
2041
+ }
2042
+ }
2043
+
1906
2044
  .sep-loss-negative {
1907
2045
  color: #9b1f1f;
1908
2046
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mantenimento-app",
3
- "version": "2.2.6",
3
+ "version": "2.2.8",
4
4
  "description": "Frontend + backend architecture for the mantenimento calculator",
5
5
  "type": "commonjs",
6
6
  "main": "backend/calculate-model.js",