diff --git a/SVS-MSP-Calculator.css b/SVS-MSP-Calculator.css index 73b9b33..cf87a01 100644 --- a/SVS-MSP-Calculator.css +++ b/SVS-MSP-Calculator.css @@ -1077,6 +1077,16 @@ .sl-otf-waived .otf-amt { text-decoration: line-through; text-decoration-color: var(--green); } .sl-otf-waived .otf-waived-label { text-decoration: none; font-weight: 600; letter-spacing: 0.06em; } + /* ── ADMIN FEE WAIVED display */ + .admin-fee-header { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; } + .admin-fee-waive-toggle { margin-left: auto; } + .admin-fee-strike { text-decoration: line-through; color: var(--muted); text-decoration-color: var(--muted); } + .admin-fee-waived-badge { font-family: 'DM Mono', monospace; font-size: 12px; font-weight: 700; letter-spacing: 0.08em; color: var(--green); background: rgba(33,112,69,0.12); border: 1px solid rgba(33,112,69,0.28); border-radius: 4px; padding: 2px 7px; vertical-align: middle; } + .sl-admin-waived > span:first-child { text-decoration: line-through; text-decoration-color: var(--muted); color: var(--muted); } + .admin-waive-savings { display: flex; align-items: center; gap: 7px; font-family: 'DM Mono', monospace; font-size: 12px; letter-spacing: 0.04em; color: var(--green); background: rgba(33,112,69,0.08); border: 1px solid rgba(33,112,69,0.22); border-radius: 6px; padding: 8px 12px; margin-top: 10px; margin-bottom: 4px; } + .admin-waive-savings.hidden { display: none; } + #adminWaivedAmt { font-weight: 700; } + /* Nudge banner internal flex rows */ .nudge-header-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; } .nudge-nav-group { display: flex; gap: 4px; } diff --git a/SVS-MSP-Calculator.html b/SVS-MSP-Calculator.html index 76d0b53..7623a07 100644 --- a/SVS-MSP-Calculator.html +++ b/SVS-MSP-Calculator.html @@ -308,6 +308,11 @@
Site Admin Fee $150/mo +
Calculated from services below · floor $150/mo
@@ -329,6 +334,11 @@ Total Admin Fee— + +
diff --git a/SVS-MSP-Calculator.js b/SVS-MSP-Calculator.js index f01f98e..94ea32c 100644 --- a/SVS-MSP-Calculator.js +++ b/SVS-MSP-Calculator.js @@ -121,6 +121,7 @@ function calcQuote() { const hstEnabled = document.getElementById('hstToggle')?.checked || false; const oneTimeFee = parseFloat(document.getElementById('oneTimeFee')?.value) || 0; const ztActive = addZT || ztSeats > 0; + const adminWaived = document.getElementById('adminWaived')?.checked || false; const VOIP_RATES = { basic: VOIP_RATE_BASIC, standard: VOIP_RATE_STANDARD, premium: VOIP_RATE_PREMIUM }; const CONTRACT_DISCOUNT = { 'm2m': DISCOUNT_M2M, '12mo': DISCOUNT_12MO, '24mo': DISCOUNT_24MO }; @@ -145,7 +146,8 @@ function calcQuote() { const baseSubtotal = userBase + endpointBase + serverBase; const siteAdminBase = Math.max(ADMIN_FEE_FLOOR, ADMIN_FEE_MINIMUM - baseSubtotal); const admin1PWM = addPWM ? Math.round(userPWM * ADMIN_1PWM_PCT) : 0; - const adminFeeNet = siteAdminBase + (ztActive ? ADMIN_FEE_ZT : 0) + admin1PWM; + const adminFeeNet = siteAdminBase + (ztActive ? ADMIN_FEE_ZT : 0) + admin1PWM; + const adminFeeEffective = adminWaived ? 0 : adminFeeNet; const ztNetSeats = ztSeats * ZT_SEAT_RATE; const ztNetRouters = ztRouters * ZT_ROUTER_RATE; @@ -157,7 +159,7 @@ function calcQuote() { const voipFaxAmt = addVoipFax ? VOIP_FAX_RATE : 0; const voipTotal = voipSeatsAmt + voipPhoneAmt + voipFaxAmt; - const MRR = userTotal + endpointTotal + adminFeeNet + ztNetTotal + voipTotal; + const MRR = userTotal + endpointTotal + adminFeeEffective + ztNetTotal + voipTotal; const annual = MRR * 12; const perUserAllin = users > 0 ? MRR / users : 0; @@ -258,7 +260,12 @@ function update() { }); // Admin Fee - getEl('adminFeeDisplay').textContent = fmt(adminFeeNet) + '/mo'; + if (adminWaived) { + getEl('adminFeeDisplay').innerHTML = + `${fmt(adminFeeNet)}/mo WAIVED`; + } else { + getEl('adminFeeDisplay').textContent = fmt(adminFeeNet) + '/mo'; + } const fillPct = Math.min(100, Math.max(0, (baseSubtotal / ADMIN_FEE_MINIMUM) * 100)); getEl('floorBar').style.width = fillPct + '%'; getEl('floorProgress').textContent = fmt(baseSubtotal) + ' / ' + fmt(ADMIN_FEE_MINIMUM); @@ -272,7 +279,19 @@ function update() { getEl('fb-zt-row').classList.toggle('hidden', !ztActive); getEl('fb-pwm-row').classList.toggle('hidden', !addPWM); getEl('fb-pwm').textContent = '+' + fmt(admin1PWM); - getEl('fb-total').textContent = fmt(adminFeeNet); + if (adminWaived) { + getEl('fb-total').innerHTML = + `${fmt(adminFeeNet)} WAIVED`; + } else { + getEl('fb-total').textContent = fmt(adminFeeNet); + } + // Savings callout below fee table + const adminWaivedSavingsEl = document.getElementById('adminWaivedSavings'); + if (adminWaivedSavingsEl) { + adminWaivedSavingsEl.classList.toggle('hidden', !adminWaived || adminFeeNet === 0); + const awAmt = document.getElementById('adminWaivedAmt'); + if (awAmt) awAmt.textContent = fmt(adminFeeNet); + } // Sidebar lines const show = (id, val) => { @@ -309,7 +328,16 @@ function update() { if (ztNetTotal > 0) getEl('sl-zt-val').textContent = fmt(ztNetTotal); show('sl-voip', voipTotal > 0); if (voipTotal > 0) getEl('sl-voip-val').textContent = fmt(voipTotal); - getEl('sl-admin-val').textContent = fmt(adminFeeNet); + const slAdminEl = getEl('sl-admin'); + const slAdminValEl = getEl('sl-admin-val'); + if (adminWaived) { + slAdminEl?.classList.add('sl-admin-waived'); + if (slAdminValEl) slAdminValEl.innerHTML = + `${fmt(adminFeeNet)} WAIVED`; + } else { + slAdminEl?.classList.remove('sl-admin-waived'); + if (slAdminValEl) slAdminValEl.textContent = fmt(adminFeeNet); + } // MRR + totals — show effective MRR (after term discount) as the headline number getEl('mrrDisplay').textContent = fmt(effectiveMrr); @@ -518,7 +546,7 @@ function updateSectionSummaries(q) { el.style.display = show ? 'inline-block' : 'none'; }; - setSummary('sec01-summary', fmt(q.adminFeeNet) + '/mo'); + setSummary('sec01-summary', q.adminWaived ? 'WAIVED' : fmt(q.adminFeeNet) + '/mo'); setSummary('sec02-summary', q.users > 0 ? `${q.users} user${q.users !== 1 ? 's' : ''} · ${fmt(q.userTotal)}/mo` : ''); setSummary('sec03-summary', q.endpoints > 0 ? `${q.endpoints} endpoint${q.endpoints !== 1 ? 's' : ''} · ${fmt(q.endpointTotal - q.serverBase)}/mo` : ''); setSummary('sec04-summary', q.servers > 0 ? `${q.servers} server${q.servers !== 1 ? 's' : ''} · ${fmt(q.serverBase)}/mo` : '');