Replaced 2 hardcoded 6px margin-bottom values with var(--space-xs) in admin-fee-header and admin-waive-savings. Removed redundant inline style="margin-bottom:16px" from sec-01 subtitle (handled by section-content * + * rule). Full visual audit across Dark/Light/Glass at 1920px, print media, and mobile (375px/600px/780px landscape) — no regressions found. Updated SESSION-HANDOFF, CLAUDE.md, DECISION-LOG, KNOWN-ISSUES, and MASTER-SESSION-PROMPT. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1013 lines
66 KiB
HTML
1013 lines
66 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>SVS MSP — Live Quote Calculator</title>
|
||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||
<link href="https://fonts.googleapis.com/css2?family=Cinzel:wght@700&family=Poppins:wght@500;600;700&family=Lato:wght@400;700&family=DM+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||
<link rel="stylesheet" href="SVS-MSP-Calculator.css">
|
||
</head>
|
||
<body>
|
||
|
||
<!-- ════════════════════════════════════════════════════════════
|
||
MOBILE FLOATING QUOTE PILL
|
||
Fixed position, top-right, z-index:200 (above header z:100).
|
||
Visible only on ≤1100px via CSS.
|
||
Shows live MRR from #mrrDisplay via update() wrapper.
|
||
Click → openMobilePanel()
|
||
════════════════════════════════════════════════════════════ -->
|
||
<button class="mobile-quote-pill" onclick="openMobilePanel()" aria-label="View quote summary">
|
||
<div class="mobile-pill-icon">
|
||
<span class="fa-icon fa-icon-file-invoice fa-icon--white" style="--icon-size:14px;"></span>
|
||
</div>
|
||
<div>
|
||
<div class="mobile-pill-mrr" id="mobilePillMrr">—</div>
|
||
<div class="mobile-pill-label">MRR</div>
|
||
</div>
|
||
</button>
|
||
|
||
<!-- ════════════════════════════════════════════════════════════
|
||
MOBILE QUOTE PANEL — full-screen bottom sheet overlay
|
||
z-index:300 (above everything). Hidden by default (opacity:0,
|
||
pointer-events:none). .open class triggers slide-up animation.
|
||
STRUCTURE:
|
||
.mobile-panel-backdrop — dark blur overlay, click to close
|
||
.mobile-panel-sheet — slides up from bottom, max-height:92vh
|
||
.mobile-panel-handle — decorative drag indicator bar
|
||
.mobile-panel-close-row — "QUOTE SUMMARY" label + × button
|
||
#mobilePanelContent — receives a JS-cloned sidebar with _m IDs
|
||
MOBILE SIDEBAR: Built from the desktop sidebar on boot.
|
||
update() syncs the cloned _m elements after each render.
|
||
Never DOM-move the real .sidebar here — it breaks desktop.
|
||
════════════════════════════════════════════════════════════ -->
|
||
<div class="mobile-quote-panel" id="mobileQuotePanel">
|
||
<div class="mobile-panel-backdrop" onclick="closeMobilePanel()"></div>
|
||
<div class="mobile-panel-sheet" id="mobilePanelSheet">
|
||
<div class="mobile-panel-handle"></div>
|
||
<div class="mobile-panel-close-row">
|
||
<span class="mobile-panel-close-title">Quote Summary</span>
|
||
<button class="mobile-panel-close-btn" onclick="closeMobilePanel()" aria-label="Close">×</button>
|
||
</div>
|
||
<div class="mobile-panel-actions">
|
||
<button class="btn-export" onclick="printInvoice()">
|
||
<span class="fa-icon fa-icon-print" style="--icon-size:14px;margin-right:7px;"></span>
|
||
Print / Save PDF
|
||
</button>
|
||
<button class="btn-export btn-export-secondary" onclick="exportQuoteJSON()">
|
||
<span class="fa-icon fa-icon-file-code" style="--icon-size:14px;margin-right:7px;"></span>
|
||
Export JSON
|
||
</button>
|
||
</div>
|
||
<!-- Sidebar content injected by JS from the desktop sidebar markup -->
|
||
<div id="mobilePanelContent"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- TOP BAR -->
|
||
<!-- ── TOP BAR ── sticky, z-index:100, cream bg (#ddd8d0) ──────── -->
|
||
<header class="top-bar">
|
||
<div class="top-bar-inner">
|
||
<svg class="top-bar-logo" height="32" viewBox="0 0 424.27 97.38" xmlns="http://www.w3.org/2000/svg">
|
||
<polyline points="7.32 8.88 62.11 8.88 34.72 58.22" fill="#1f75a6"/>
|
||
<polyline points="40.7 55.33 64.4 12.64 71.88 12.64 44.48 61.99 40.7 55.33" fill="#8d252f"/>
|
||
<path d="M110.03,89.91c-5.99,0-11.27-.66-15.86-1.99-4.59-1.33-8.6-3.2-12.05-5.63-3.45-2.42-6.54-5.27-9.27-8.53l14.21-15.92c3.79,4.85,7.75,8.05,11.88,9.61,4.13,1.55,8.01,2.33,11.65,2.33,1.44,0,2.73-.13,3.87-.4,1.14-.26,2.01-.7,2.62-1.31.61-.61.91-1.44.91-2.5,0-.98-.32-1.82-.97-2.5-.65-.68-1.5-1.27-2.56-1.76-1.06-.49-2.22-.91-3.47-1.25-1.25-.34-2.46-.62-3.64-.85-1.18-.23-2.22-.46-3.13-.68-4.55-1.06-8.53-2.35-11.94-3.87-3.41-1.51-6.25-3.33-8.53-5.46-2.27-2.12-3.96-4.55-5.06-7.28-1.1-2.73-1.65-5.8-1.65-9.21,0-3.87.89-7.39,2.67-10.57,1.78-3.18,4.17-5.91,7.16-8.19,2.99-2.27,6.4-4.02,10.23-5.23,3.83-1.21,7.79-1.82,11.88-1.82,5.99,0,10.99.55,15.01,1.65,4.02,1.1,7.39,2.67,10.12,4.72,2.73,2.05,5.08,4.43,7.05,7.16l-14.32,13.76c-1.67-1.59-3.41-2.9-5.23-3.92-1.82-1.02-3.7-1.78-5.63-2.27-1.93-.49-3.85-.74-5.74-.74-1.74,0-3.22.13-4.43.4-1.21.27-2.16.68-2.84,1.25-.68.57-1.02,1.35-1.02,2.33s.43,1.8,1.31,2.44c.87.64,1.97,1.19,3.3,1.65,1.32.46,2.65.82,3.98,1.08,1.33.27,2.44.47,3.35.62,4.17.76,8,1.8,11.48,3.13,3.49,1.33,6.54,3,9.15,5,2.61,2.01,4.62,4.51,6.03,7.5,1.4,3,2.1,6.54,2.1,10.63,0,5.84-1.46,10.73-4.38,14.67-2.92,3.94-6.84,6.92-11.77,8.92-4.93,2.01-10.42,3.01-16.48,3.01Z" fill="#0c0c0c"/>
|
||
<path d="M174.27,88.77l-31.72-79.58h24.56l12.73,34.79c.91,2.35,1.65,4.36,2.22,6.03.57,1.67,1.08,3.24,1.54,4.72.46,1.48.89,3.05,1.31,4.72.42,1.67.89,3.71,1.42,6.14h-3.98c.76-3.18,1.42-5.8,1.99-7.84.57-2.05,1.21-4.07,1.93-6.08.72-2.01,1.65-4.56,2.79-7.67l12.73-34.79h23.76l-31.95,79.58h-19.33Z" fill="#0c0c0c"/>
|
||
<path d="M257.94,89.91c-5.99,0-11.27-.66-15.86-1.99-4.59-1.33-8.6-3.2-12.05-5.63-3.45-2.42-6.54-5.27-9.27-8.53l14.21-15.92c3.79,4.85,7.75,8.05,11.88,9.61,4.13,1.55,8.02,2.33,11.65,2.33,1.44,0,2.73-.13,3.87-.4,1.14-.26,2.01-.7,2.62-1.31.61-.61.91-1.44.91-2.5,0-.98-.32-1.82-.97-2.5-.64-.68-1.5-1.27-2.56-1.76-1.06-.49-2.22-.91-3.47-1.25-1.25-.34-2.46-.62-3.64-.85-1.18-.23-2.22-.46-3.13-.68-4.55-1.06-8.53-2.35-11.94-3.87-3.41-1.51-6.25-3.33-8.53-5.46-2.27-2.12-3.96-4.55-5.06-7.28-1.1-2.73-1.65-5.8-1.65-9.21,0-3.87.89-7.39,2.67-10.57,1.78-3.18,4.17-5.91,7.16-8.19,2.99-2.27,6.4-4.02,10.23-5.23,3.83-1.21,7.79-1.82,11.88-1.82,5.99,0,10.99.55,15.01,1.65,4.02,1.1,7.39,2.67,10.12,4.72,2.73,2.05,5.08,4.43,7.05,7.16l-14.33,13.76c-1.67-1.59-3.41-2.9-5.23-3.92-1.82-1.02-3.69-1.78-5.63-2.27-1.93-.49-3.85-.74-5.74-.74-1.74,0-3.22.13-4.43.4-1.21.27-2.16.68-2.84,1.25-.68.57-1.02,1.35-1.02,2.33s.44,1.8,1.31,2.44c.87.64,1.97,1.19,3.3,1.65,1.33.46,2.65.82,3.98,1.08,1.33.27,2.44.47,3.35.62,4.17.76,8,1.8,11.48,3.13,3.49,1.33,6.54,3,9.15,5,2.62,2.01,4.62,4.51,6.03,7.5,1.4,3,2.1,6.54,2.1,10.63,0,5.84-1.46,10.73-4.38,14.67-2.92,3.94-6.84,6.92-11.77,8.92-4.93,2.01-10.42,3.01-16.48,3.01Z" fill="#0c0c0c"/>
|
||
<path d="M300.67,47.36V8.02h10.45l14.33,23.33-8.49-.06,14.5-23.27h10.12v39.35h-11.69v-9.39c0-3.37.08-6.41.25-9.11.17-2.7.46-5.38.87-8.04l1.35,3.54-9.5,14.73h-3.71l-9.33-14.73,1.41-3.54c.41,2.51.7,5.09.87,7.73.17,2.64.25,5.78.25,9.42v9.39h-11.69Z" fill="#0c0c0c"/>
|
||
<path d="M364.36,47.93c-2.96,0-5.57-.33-7.84-.98-2.27-.66-4.25-1.58-5.96-2.78-1.71-1.2-3.23-2.6-4.58-4.22l7.03-7.87c1.87,2.4,3.83,3.98,5.87,4.75,2.04.77,3.96,1.15,5.76,1.15.71,0,1.35-.07,1.91-.2.56-.13.99-.35,1.29-.65.3-.3.45-.71.45-1.24,0-.49-.16-.9-.48-1.24s-.74-.63-1.26-.87c-.53-.24-1.1-.45-1.71-.62-.62-.17-1.22-.31-1.8-.42-.58-.11-1.1-.22-1.55-.34-2.25-.52-4.22-1.16-5.9-1.91-1.69-.75-3.09-1.65-4.22-2.7-1.12-1.05-1.96-2.25-2.5-3.6-.54-1.35-.81-2.87-.81-4.55,0-1.91.44-3.65,1.32-5.23.88-1.57,2.06-2.92,3.54-4.05s3.17-1.99,5.06-2.58,3.85-.9,5.87-.9c2.96,0,5.43.27,7.42.81,1.99.54,3.65,1.32,5,2.33,1.35,1.01,2.51,2.19,3.49,3.54l-7.08,6.8c-.83-.79-1.69-1.43-2.59-1.94s-1.83-.88-2.78-1.12c-.96-.24-1.9-.37-2.84-.37-.86,0-1.59.07-2.19.2-.6.13-1.07.34-1.41.62-.34.28-.51.67-.51,1.15s.21.89.65,1.21c.43.32.97.59,1.63.82.66.22,1.31.4,1.97.53.66.13,1.21.23,1.66.31,2.06.38,3.95.89,5.68,1.55,1.72.66,3.23,1.48,4.53,2.47s2.29,2.23,2.98,3.71c.69,1.48,1.04,3.23,1.04,5.26,0,2.89-.72,5.3-2.16,7.25-1.44,1.95-3.38,3.42-5.82,4.41-2.44.99-5.15,1.49-8.15,1.49Z" fill="#0c0c0c"/>
|
||
<path d="M386.61,47.36V8.02h17.71c2.7,0,5.1.58,7.2,1.74,2.1,1.16,3.75,2.75,4.95,4.78,1.2,2.02,1.8,4.35,1.8,6.97s-.6,5.17-1.8,7.31c-1.2,2.14-2.85,3.81-4.95,5.03-2.1,1.22-4.5,1.83-7.2,1.83h-5.56v11.69h-12.14ZM398.53,25.33h3.54c.71,0,1.35-.14,1.91-.42.56-.28,1-.68,1.32-1.21.32-.52.48-1.18.48-1.97s-.16-1.42-.48-1.91c-.32-.49-.76-.85-1.32-1.1-.56-.24-1.2-.37-1.91-.37h-3.54v6.97Z" fill="#0c0c0c"/>
|
||
</svg>
|
||
<div class="top-bar-right">
|
||
<span id="quoteRef">SVS-00000000-0000</span><br>
|
||
<span id="headerDate">—</span>
|
||
</div>
|
||
<button id="themeToggle" class="theme-toggle-btn" onclick="toggleTheme()" aria-label="Toggle light/dark theme" title="Switch to light theme">
|
||
<span id="themeToggleIcon"><span class="fa-icon fa-icon-moon-stars fa-icon--theme" style="--icon-size:15px;"></span></span>
|
||
</button>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- ── MAIN LAYOUT GRID: 3fr main-col | 2fr side-col ────────────── -->
|
||
<div class="outer">
|
||
<!-- ── LEFT COLUMN: sections I–VI + client bar ──────────────────── -->
|
||
<div class="main-col">
|
||
|
||
<!-- CLIENT BAR -->
|
||
<div class="client-bar">
|
||
<div class="client-label">Prepared for</div>
|
||
<input class="client-input" id="clientName" type="text" placeholder="Client Name" oninput="update()">
|
||
<div class="client-rep-row">
|
||
<div class="client-label">Prepared by</div>
|
||
<input class="client-input client-input--rep" id="repName" type="text" placeholder="Your Name" oninput="debouncedSave()">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="sections-toolbar">
|
||
<button class="btn-toggle-all" id="toggleAllBtn" onclick="toggleAllSections()">
|
||
<span class="toggle-all-collapse-icon" style="display:none;"><span class="fa-icon fa-icon-angles-up" style="--icon-size:11px;margin-right:5px;"></span></span>
|
||
<span class="toggle-all-expand-icon"><span class="fa-icon fa-icon-angles-down" style="--icon-size:11px;margin-right:5px;"></span></span>
|
||
<span class="toggle-all-label">Expand All</span>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- ── QUOTE SETTINGS BAR ────────────────────────────────────────
|
||
Contract term toggle (3-way) and onboarding fee.
|
||
Contract term drives discountPct in calcQuote().
|
||
HST toggle shows/hides the +13% line in the sidebar.
|
||
One-time fee is included in JSON export but NOT in MRR.
|
||
──────────────────────────────────────────────────────────────── -->
|
||
<div class="quote-settings-bar">
|
||
<div class="qs-group">
|
||
<div class="qs-label-row">
|
||
<div class="qs-label">Contract Term & Incentives</div>
|
||
</div>
|
||
<div class="tier-seg-wrap qs-term-wrap">
|
||
<input type="radio" name="contractTerm" id="termM2m" value="m2m" checked onchange="update()">
|
||
<label for="termM2m" class="tier-seg" id="seg-term-m2m">
|
||
<div class="tier-name">Month-to-Month</div>
|
||
<div class="tier-sub">Maximum flexibility</div>
|
||
</label>
|
||
<input type="radio" name="contractTerm" id="term12mo" value="12mo" onchange="update()">
|
||
<label for="term12mo" class="tier-seg" id="seg-term-12mo">
|
||
<div class="tier-name">12-Month</div>
|
||
<div class="tier-sub qs-discount-sub">3% off MRR + 50% off onboarding</div>
|
||
</label>
|
||
<input type="radio" name="contractTerm" id="term24mo" value="24mo" onchange="update()">
|
||
<label for="term24mo" class="tier-seg" id="seg-term-24mo">
|
||
<div class="tier-name">24-Month <span class="qs-best-badge">Best Value</span></div>
|
||
<div class="tier-sub qs-discount-sub">5% off MRR + complimentary onboarding</div>
|
||
</label>
|
||
</div>
|
||
<div class="qs-savings-stack">
|
||
<div class="qs-savings-row hidden" id="qsSavingsDisplay">
|
||
<span class="fa-icon fa-icon-square-check" style="--icon-size:15px;"></span>
|
||
<span id="qsSavingsCopy">Saving $0/mo vs. month-to-month</span>
|
||
</div>
|
||
<div class="qs-savings-row hidden" id="qsFirstYearDisplay">
|
||
<span class="fa-icon fa-icon-square-check" style="--icon-size:15px;"></span>
|
||
<span id="qsFirstYearCopy">Year-one value unlocked: $0 from term savings and complimentary onboarding</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="qs-divider"></div>
|
||
<div class="qs-right">
|
||
<div class="qs-fee-row">
|
||
<div class="qs-fee-header">
|
||
<label class="qs-fee-label" for="oneTimeFee">Onboarding / Implementation</label>
|
||
</div>
|
||
<div class="qs-fee-input-wrap">
|
||
<span class="qs-fee-dollar">$</span>
|
||
<input type="number" id="oneTimeFee" class="qs-fee-input" min="0" placeholder="auto" oninput="this.dataset.manual='1'; update();">
|
||
</div>
|
||
<label class="qs-toggle-row qs-fee-waive">
|
||
<input type="checkbox" id="onboardingWaived" onchange="onWaiveToggle();">
|
||
<span class="qs-switch"></span>
|
||
<span class="qs-toggle-label">Waive</span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="group-label">Managed IT Services <span class="group-label-sections">(Sections I, II, III)</span></div>
|
||
|
||
<!-- ────────────────────────────────────────────────────────────
|
||
SECTION I — SITE ADMIN FEE
|
||
id="sec-01" starts collapsed
|
||
#adminFeeDisplay — rendered by update() → fmt(adminFeeNet)
|
||
#floorBar — progress bar width%, turns green at 100%
|
||
#floorProgress — "$X / $650" text label
|
||
#floorNote — threshold status message
|
||
#fb-base — siteAdminBase value
|
||
#fb-zt-row — hidden unless ztActive
|
||
#fb-pwm-row — hidden unless addPWM
|
||
#fb-total — adminFeeNet total
|
||
#sec01-summary — badge shown when section collapsed
|
||
──────────────────────────────────────────────────────────────── -->
|
||
<div class="section" id="sec-01">
|
||
<div class="section-header section-toggle" onclick="toggleSection('sec-01')" aria-expanded="false" tabindex="0" role="button" onkeydown="if(event.key==='Enter'||event.key===' '){toggleSection('sec-01');event.preventDefault();}">
|
||
<div class="section-num">III</div>
|
||
<div class="section-title-block">
|
||
<div class="section-title">Site Management</div>
|
||
</div>
|
||
<div class="sec-chevron"><span class="fa-icon fa-icon-chevron-down" style="--icon-size:14px;"></span></div>
|
||
<div class="sec-controls-row">
|
||
<span class="section-badge">Operational Oversight</span>
|
||
<span id="sec01-summary" class="sec-summary-badge"></span>
|
||
</div>
|
||
</div>
|
||
<!-- Always-visible threshold bar (outside section-body so it shows when collapsed) -->
|
||
<div class="progress-wrap sec-01-threshold">
|
||
<div class="progress-label">
|
||
<span>Managed Service Threshold</span>
|
||
</div>
|
||
<div class="progress-track">
|
||
<div class="progress-fill" id="floorBar" style="width:0%"></div>
|
||
</div>
|
||
</div>
|
||
<div id="floorNote" class="floor-note sec-01-threshold"></div>
|
||
<div class="section-body" id="sec-01-body" style="display:none;">
|
||
<div class="section-content">
|
||
|
||
<div class="section-subtitle">Ongoing oversight for your environment, vendors, and IT documentation so everything stays coordinated, accountable, and easier to support.</div>
|
||
|
||
<div class="admin-fee-header">
|
||
<span class="admin-fee-title">Site Admin Fee</span>
|
||
<span id="adminFeeDisplay" class="admin-fee-val">$150/mo</span>
|
||
<label class="qs-toggle-row admin-fee-waive-toggle">
|
||
<input type="checkbox" id="adminWaived" onchange="update()">
|
||
<span class="qs-switch"></span>
|
||
<span class="qs-toggle-label">Waive</span>
|
||
</label>
|
||
</div>
|
||
|
||
<table class="fee-table" id="feeBreakdown">
|
||
<tr><td>Base Site Admin</td><td id="fb-base">—</td></tr>
|
||
<tr id="fb-zt-row" class="hidden"><td>Zero Trust Supplement</td><td id="fb-zt">+$250</td></tr>
|
||
<tr id="fb-pwm-row" class="hidden"><td>1Password Admin (10%)</td><td id="fb-pwm">—</td></tr>
|
||
<tr class="fee-total"><td>Total Admin Fee</td><td id="fb-total">—</td></tr>
|
||
</table>
|
||
|
||
<div class="admin-waive-savings hidden" id="adminWaivedSavings">
|
||
<span class="fa-icon fa-icon-square-check" style="--icon-size:11px;"></span>
|
||
Site oversight fee waived on this quote — included by SVS on this proposal, saving <span id="adminWaivedAmt">$0</span>/mo
|
||
</div>
|
||
|
||
<!-- What's Covered collapsible -->
|
||
<div class="collapsible-header collapsible-header--mt16" onclick="toggleCollapsible('adminCovered')" aria-expanded="false" tabindex="0" role="button" onkeydown="if(event.key==='Enter'||event.key===' '){toggleCollapsible('adminCovered');event.preventDefault();}">
|
||
<span class="collapsible-toggle" id="adminCovered-icon"><span class="fa-icon fa-icon-chevron-down" style="--icon-size:12px;"></span></span>
|
||
<span class="collapsible-label">What This Fee Covers Behind the Scenes</span>
|
||
</div>
|
||
<div class="collapsible-body" id="adminCovered">
|
||
<div class="feature-card-grid">
|
||
<div class="feature-card"><div class="feature-card-title"><span class="fa-icon fa-icon-users-gear fa-icon--accent" style="--icon-size:16px;margin-right:8px;"></span> Tenant & Identity Management</div><div class="feature-card-desc">Microsoft 365 / Entra ID tenant administration, user lifecycle, MFA enforcement, and conditional access policies.</div></div>
|
||
<div class="feature-card"><div class="feature-card-title"><span class="fa-icon fa-icon-network-wired fa-icon--accent" style="--icon-size:16px;margin-right:8px;"></span> Network & Infrastructure Oversight</div><div class="feature-card-desc">Firewall configuration reviews, DNS management, VLAN segmentation oversight, and network performance monitoring.</div></div>
|
||
<div class="feature-card"><div class="feature-card-title"><span class="fa-icon fa-icon-book-open-cover fa-icon--accent" style="--icon-size:15px;margin-right:8px;"></span> Documentation & Runbooks</div><div class="feature-card-desc">Living IT documentation, network diagrams, asset registers, and runbooks updated continuously in your client portal.</div></div>
|
||
<div class="feature-card"><div class="feature-card-title"><span class="fa-icon fa-icon-handshake fa-icon--accent" style="--icon-size:16px;margin-right:8px;"></span> Vendor Management</div><div class="feature-card-desc">Single point of contact for all technology vendors — ISPs, software, hardware, and cloud providers.</div></div>
|
||
<div class="feature-card"><div class="feature-card-title"><span class="fa-icon fa-icon-shield-check fa-icon--accent" style="--icon-size:15px;margin-right:8px;"></span> Security Posture Management</div><div class="feature-card-desc">Monthly security reviews, vulnerability scan oversight, patch compliance reporting, and security baseline enforcement.</div></div>
|
||
<div class="feature-card"><div class="feature-card-title"><span class="fa-icon fa-icon-chart-line-up fa-icon--accent" style="--icon-size:16px;margin-right:8px;"></span> Reporting & QBRs</div><div class="feature-card-desc">Monthly infrastructure health reports, ticket trend analysis, and quarterly business reviews with your account manager.</div></div>
|
||
<div class="feature-card"><div class="feature-card-title"><span class="fa-icon fa-icon-cloud fa-icon--accent" style="--icon-size:18px;margin-right:8px;"></span> Cloud Governance</div><div class="feature-card-desc">License optimization, cloud spend visibility, Microsoft Secure Score improvement, and policy compliance alignment.</div></div>
|
||
<div class="feature-card"><div class="feature-card-title"><span class="fa-icon fa-icon-triangle-exclamation fa-icon--accent" style="--icon-size:16px;margin-right:8px;"></span> Incident Coordination</div><div class="feature-card-desc">Major incident management, root cause analysis, and coordinated response across all your managed services.</div></div>
|
||
<div class="feature-card"><div class="feature-card-title"><span class="fa-icon fa-icon-hard-drive fa-icon--accent" style="--icon-size:18px;margin-right:8px;"></span> Backup Monitoring</div><div class="feature-card-desc">Daily backup job verification, restore testing schedules, retention compliance checks, and failure alerting — separate from the Bare Metal Backup add-on.</div></div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ────────────────────────────────────────────────────────────
|
||
SECTION II — USER PACKAGE
|
||
#rateM365 / #rateBYOL — radio inputs, read by calcQuote()
|
||
#byolCalloutGreen — shown when M365 selected (byol=false)
|
||
#byolCalloutRed — shown when BYOL selected (byol=true)
|
||
#byolRedSavings — dynamic savings $ inside red callout
|
||
#userCount — number input → users in calcQuote()
|
||
Add-ons: #addExtHours #addPWM #addINKY #addZT (checkboxes)
|
||
Row highlights: #row-ext #row-pwm #row-inky #row-zt
|
||
#sec02-summary — badge shown when collapsed
|
||
──────────────────────────────────────────────────────────────── -->
|
||
<div class="section" id="sec-02">
|
||
<div class="section-header section-toggle" onclick="toggleSection('sec-02')" aria-expanded="false" tabindex="0" role="button" onkeydown="if(event.key==='Enter'||event.key===' '){toggleSection('sec-02');event.preventDefault();}">
|
||
<div class="section-num">I</div>
|
||
<div class="section-title-block">
|
||
<div class="section-title">User Package</div>
|
||
</div>
|
||
<div class="sec-chevron"><span class="fa-icon fa-icon-chevron-down" style="--icon-size:14px;"></span></div>
|
||
<div class="sec-controls-row" onclick="event.stopPropagation()">
|
||
<div class="num-stepper">
|
||
<button class="step-btn" aria-label="Decrease users" onclick="stepInput('userCount',-1)">−</button>
|
||
<input class="num-input" id="userCount" type="number" min="0" value="1" oninput="update()">
|
||
<button class="step-btn" aria-label="Increase users" onclick="stepInput('userCount',1)">+</button>
|
||
</div>
|
||
<span class="section-badge">Managed Users</span>
|
||
<span id="sec02-summary" class="sec-summary-badge"></span>
|
||
</div>
|
||
<div class="section-subtitle">Per-user managed productivity, identity, security, and helpdesk with one clear recommended path for most clients.</div>
|
||
</div>
|
||
<div class="section-body" id="sec-02-body" style="display:none;">
|
||
<div class="section-content">
|
||
|
||
<!-- Base Rate Toggle -->
|
||
<div class="pill-toggle">
|
||
<input type="radio" name="baseRate" id="rateM365" value="m365" checked onchange="update()">
|
||
<label for="rateM365">
|
||
<span class="pill-price">
|
||
<span id="m365PriceM2m">$140</span><span id="m365PriceAnnual" class="hidden">$130</span><small>/user/mo</small>
|
||
</span>
|
||
<span class="pill-desc">M365 Included — Recommended for most clients: licensing, identity, email & business protection in one seat</span>
|
||
<span class="pill-savings" id="m365SavingsLine"></span>
|
||
</label>
|
||
<input type="radio" name="baseRate" id="rateBYOL" value="byol" onchange="update()">
|
||
<label for="rateBYOL">
|
||
<span class="pill-price">$110<small>/user/mo</small></span>
|
||
<span class="pill-desc">BYOL — Best when the client already has a licensing standard they need to keep (M365 or Google Workspace)</span>
|
||
</label>
|
||
</div>
|
||
|
||
<div id="byolCalloutGreen" class="callout-green">
|
||
<span class="fa-icon fa-icon-square-check fa-icon--green" style="--icon-size:14px;margin-top:2px;"></span><span id="m365CalloutText">Recommended bundle — M365 Business Premium is built into this seat and can save up to $11/user/mo versus buying it retail on its own</span>
|
||
</div>
|
||
<div id="byolCalloutRed" class="callout-red hidden">
|
||
<span class="fa-icon fa-icon-triangle-exclamation fa-icon--amber" style="--icon-size:14px;margin-top:2px;"></span><span>Client-owned licensing selected — switching to the bundled M365 seat would recover up to <span id="byolRedSavings">$150</span>/mo in retail-equivalent spend</span>
|
||
</div>
|
||
|
||
<div class="m365-app-strip" id="userBundleStrip" aria-label="Microsoft 365 apps included with the bundled seat">
|
||
<div class="m365-app-list">
|
||
<div class="m365-app-item">
|
||
<img src="M365icons/word.svg" alt="Microsoft Word" class="m365-app-icon">
|
||
<span class="m365-app-name">Word</span>
|
||
</div>
|
||
<div class="m365-app-item">
|
||
<img src="M365icons/excel.svg" alt="Microsoft Excel" class="m365-app-icon">
|
||
<span class="m365-app-name">Excel</span>
|
||
</div>
|
||
<div class="m365-app-item">
|
||
<img src="M365icons/powerpoint.svg" alt="Microsoft PowerPoint" class="m365-app-icon">
|
||
<span class="m365-app-name">PowerPoint</span>
|
||
</div>
|
||
<div class="m365-app-item">
|
||
<img src="M365icons/outlook-svgrepo-com.svg" alt="Microsoft Outlook" class="m365-app-icon">
|
||
<span class="m365-app-name">Outlook</span>
|
||
</div>
|
||
<div class="m365-app-item">
|
||
<img src="M365icons/teams.svg" alt="Microsoft Teams" class="m365-app-icon">
|
||
<span class="m365-app-name">Teams</span>
|
||
</div>
|
||
<div class="m365-app-item">
|
||
<img src="M365icons/azure-svgrepo-com.svg" alt="Microsoft Azure" class="m365-app-icon">
|
||
<span class="m365-app-name">Azure AD</span>
|
||
</div>
|
||
</div>
|
||
<div class="m365-app-strip-note">
|
||
<span class="m365-app-note-default">Included with the bundled Microsoft 365 seat</span>
|
||
<span class="m365-app-note-byol">Not included with BYOL</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- What's Included collapsible -->
|
||
<div class="collapsible-header" onclick="toggleCollapsible('userIncluded')" aria-expanded="false" tabindex="0" role="button" onkeydown="if(event.key==='Enter'||event.key===' '){toggleCollapsible('userIncluded');event.preventDefault();}">
|
||
<span class="collapsible-toggle" id="userIncluded-icon"><span class="fa-icon fa-icon-chevron-down" style="--icon-size:12px;"></span></span>
|
||
<span class="collapsible-label">What's Included in This Package</span>
|
||
</div>
|
||
<div class="collapsible-body" id="userIncluded">
|
||
<ul class="feature-list">
|
||
<li class="m365-feature">Microsoft 365 Business Premium</li>
|
||
<li class="m365-feature">Word, Excel, PowerPoint, Teams, Exchange</li>
|
||
<li class="m365-feature">Entra ID / conditional access / SSO</li>
|
||
<li class="m365-feature">Defender for Business</li>
|
||
<li class="m365-feature">MFA enforcement</li>
|
||
<li class="m365-feature">SaaS alerting / geo-location lock</li>
|
||
<li>CORK cyber warranty with $100,000 annual coverage</li>
|
||
<li>INKY advanced mail protection</li>
|
||
<li>Security awareness training and phishing simulation</li>
|
||
<li>SaaS backup for business email, OneDrive, and Google Workspace</li>
|
||
<li>Dark web ID scanning</li>
|
||
<li>SOC account monitoring</li>
|
||
<li>Unlimited remote bilingual help desk support (9am-5pm / Mon-Fri)</li>
|
||
</ul>
|
||
</div>
|
||
|
||
|
||
<!-- Per-User Add-Ons collapsible -->
|
||
<div class="collapsible-header collapsible-header--addon" onclick="toggleCollapsible('addonsA')" aria-expanded="false" tabindex="0" role="button" onkeydown="if(event.key==='Enter'||event.key===' '){toggleCollapsible('addonsA');event.preventDefault();}">
|
||
<span class="collapsible-toggle" id="addonsA-icon"><span class="fa-icon fa-icon-chevron-down" style="--icon-size:12px;"></span></span>
|
||
<span class="collapsible-label">WORKFORCE ADD-ONS</span>
|
||
<div id="addonsA-preview" class="addon-preview-wrap">
|
||
<span class="addon-preview-pill" data-addon="addExtHours">Extended Hours</span>
|
||
<span class="addon-preview-pill" data-addon="addPWM">1Password</span>
|
||
<span class="addon-preview-pill" data-addon="addINKY">INKY Pro Upgrade</span>
|
||
<span class="addon-preview-pill" data-addon="addZT">Zero Trust</span>
|
||
</div>
|
||
</div>
|
||
<div class="collapsible-body" id="addonsA">
|
||
<div class="addon-grid">
|
||
<label class="addon-row" id="row-ext" onclick="toggleAddon('addExtHours','row-ext');update()">
|
||
<input type="checkbox" id="addExtHours">
|
||
<div><div class="addon-name">Extended Help Desk Hours</div><div class="addon-desc">8am–8pm Mon–Fri coverage via staggered shifts</div></div>
|
||
<span class="addon-price" data-price-key="ADDON_EXT_HOURS" data-price-unit="user">+$25/user/mo</span>
|
||
</label>
|
||
<label class="addon-row" id="row-pwm" onclick="toggleAddon('addPWM','row-pwm');update()">
|
||
<input type="checkbox" id="addPWM">
|
||
<div><div class="addon-name">1Password Management</div><div class="addon-desc">Business password vault, admin console & SSO integration</div></div>
|
||
<span class="addon-price" data-price-key="ADDON_1PASSWORD" data-price-unit="user">+$9/user/mo</span>
|
||
</label>
|
||
<label class="addon-row" id="row-inky" onclick="toggleAddon('addINKY','row-inky');update()">
|
||
<input type="checkbox" id="addINKY">
|
||
<div><div class="addon-name">INKY Pro Upgrade</div><div class="addon-desc">Adds enhanced phishing defense and email security controls on top of the included INKY mail protection</div></div>
|
||
<span class="addon-price" data-price-key="ADDON_INKY" data-price-unit="user">+$8/user/mo</span>
|
||
</label>
|
||
<label class="addon-row" id="row-zt" onclick="toggleAddon('addZT','row-zt');update()">
|
||
<input type="checkbox" id="addZT">
|
||
<div><div class="addon-name">Zero Trust User Seat</div><div class="addon-desc">Cytracom ZT identity-aware access — deny by default network control</div></div>
|
||
<span class="addon-price" data-price-key="ADDON_ZERO_TRUST_USER" data-price-unit="user">+$55/user/mo</span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ────────────────────────────────────────────────────────────
|
||
SECTION III — ENDPOINT PACKAGE
|
||
#endpointCount — number input → endpoints in calcQuote()
|
||
Add-ons: #addBMB (+$25/endpoint) #addUSB (+$4/endpoint)
|
||
Row highlights: #row-bmb #row-usb
|
||
#sec03-summary — badge shown when collapsed
|
||
──────────────────────────────────────────────────────────────── -->
|
||
<div class="section" id="sec-03">
|
||
<div class="section-header section-toggle" onclick="toggleSection('sec-03')" aria-expanded="false" tabindex="0" role="button" onkeydown="if(event.key==='Enter'||event.key===' '){toggleSection('sec-03');event.preventDefault();}">
|
||
<div class="section-num">II</div>
|
||
<div class="section-title-block">
|
||
<div class="section-title">Endpoint Package</div>
|
||
</div>
|
||
<div class="sec-chevron"><span class="fa-icon fa-icon-chevron-down" style="--icon-size:14px;"></span></div>
|
||
<div class="sec-controls-row" onclick="event.stopPropagation()">
|
||
<div class="num-stepper">
|
||
<button class="step-btn" aria-label="Decrease endpoints" onclick="stepInput('endpointCount',-1)">−</button>
|
||
<input class="num-input" id="endpointCount" type="number" min="0" value="1" oninput="update()">
|
||
<button class="step-btn" aria-label="Increase endpoints" onclick="stepInput('endpointCount',1)">+</button>
|
||
</div>
|
||
<span class="section-badge">Protected Endpoints</span>
|
||
<span id="sec03-summary" class="sec-summary-badge"></span>
|
||
</div>
|
||
<div class="section-subtitle">Per-device managed protection built to reduce downtime and recovery risk across workstations and laptops.</div>
|
||
</div>
|
||
<div class="section-body" id="sec-03-body" style="display:none;">
|
||
<div class="section-content">
|
||
|
||
<!-- What's Included collapsible -->
|
||
<div class="collapsible-header" onclick="toggleCollapsible('endpointIncluded')" aria-expanded="false" tabindex="0" role="button" onkeydown="if(event.key==='Enter'||event.key===' '){toggleCollapsible('endpointIncluded');event.preventDefault();}">
|
||
<span class="collapsible-toggle" id="endpointIncluded-icon"><span class="fa-icon fa-icon-chevron-down" style="--icon-size:12px;"></span></span>
|
||
<span class="collapsible-label">What's Included in This Package</span>
|
||
</div>
|
||
<div class="collapsible-body" id="endpointIncluded">
|
||
<ul class="feature-list">
|
||
<li>Managed EDR threat protection</li>
|
||
<li>1 full workstation backup included</li>
|
||
<li>24/7 SOC monitoring and response</li>
|
||
<li>Encryption enforcement</li>
|
||
<li>RMM monitoring and maintenance</li>
|
||
<li>Firmware, updates, and patch management</li>
|
||
<li>Admin password rotation</li>
|
||
<li>Application ringfencing</li>
|
||
</ul>
|
||
</div>
|
||
|
||
|
||
<!-- Per-Endpoint Add-Ons collapsible -->
|
||
<div class="collapsible-header collapsible-header--addon" onclick="toggleCollapsible('addonsB')" aria-expanded="false" tabindex="0" role="button" onkeydown="if(event.key==='Enter'||event.key===' '){toggleCollapsible('addonsB');event.preventDefault();}">
|
||
<span class="collapsible-toggle" id="addonsB-icon"><span class="fa-icon fa-icon-chevron-down" style="--icon-size:12px;"></span></span>
|
||
<span class="collapsible-label">ENDPOINT BUSINESSGUARD ADD-ONS</span>
|
||
<div id="addonsB-preview" class="addon-preview-wrap">
|
||
<span class="addon-preview-pill" data-addon="addBMB">Bare Metal Backup</span>
|
||
<span class="addon-preview-pill" data-addon="addUSB">USB Blocking</span>
|
||
</div>
|
||
</div>
|
||
<div class="collapsible-body" id="addonsB">
|
||
<div class="addon-grid">
|
||
<label class="addon-row" id="row-bmb" onclick="toggleAddon('addBMB','row-bmb');update()">
|
||
<input type="checkbox" id="addBMB">
|
||
<div><div class="addon-name">Bare Metal Backup</div><div class="addon-desc">Image-based backup with bare metal restore — fast full-device recovery with local & cloud retention</div></div>
|
||
<span class="addon-price" data-price-key="ADDON_BARE_METAL_BACKUP" data-price-unit="endpoint">+$25/endpoint/mo</span>
|
||
</label>
|
||
<label class="addon-row" id="row-usb" onclick="toggleAddon('addUSB','row-usb');update()">
|
||
<input type="checkbox" id="addUSB">
|
||
<div><div class="addon-name">USB Device Blocking</div><div class="addon-desc">Policy-enforced USB control to reduce malware and data-loss exposure from removable media</div></div>
|
||
<span class="addon-price" data-price-key="ADDON_USB_BLOCKING" data-price-unit="endpoint">+$4/endpoint/mo</span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<hr class="group-divider">
|
||
|
||
<!-- ────────────────────────────────────────────────────────────
|
||
SECTION IV — SERVER MANAGEMENT
|
||
Starts COLLAPSED (no sec-open class, body display:none)
|
||
#serverCount — number input → servers in calcQuote()
|
||
Rate: $120/server/mo (serverBase = servers * 120)
|
||
Counted in baseSubtotal → affects admin fee threshold
|
||
#sec04-summary — badge shown when collapsed
|
||
──────────────────────────────────────────────────────────────── -->
|
||
<div class="section" id="sec-04">
|
||
<div class="section-header section-toggle" onclick="toggleSection('sec-04')" aria-expanded="false" tabindex="0" role="button" onkeydown="if(event.key==='Enter'||event.key===' '){toggleSection('sec-04');event.preventDefault();}">
|
||
<div class="section-num">IV</div>
|
||
<div class="section-title-block">
|
||
<div class="section-title">Server Management</div>
|
||
</div>
|
||
<div class="sec-chevron"><span class="fa-icon fa-icon-chevron-down" style="--icon-size:14px;"></span></div>
|
||
<div class="sec-controls-row" onclick="event.stopPropagation()">
|
||
<div class="num-stepper">
|
||
<button class="step-btn" aria-label="Decrease servers" onclick="stepInput('serverCount',-1)">−</button>
|
||
<input class="num-input" id="serverCount" type="number" min="0" value="0" oninput="update()">
|
||
<button class="step-btn" aria-label="Increase servers" onclick="stepInput('serverCount',1)">+</button>
|
||
</div>
|
||
<span class="section-badge">Managed Servers</span>
|
||
<span id="sec04-summary" class="sec-summary-badge"></span>
|
||
</div>
|
||
<div class="section-subtitle">Dedicated management for physical & virtual servers</div>
|
||
</div>
|
||
<div class="section-body" id="sec-04-body" style="display:none;">
|
||
<div class="section-content">
|
||
|
||
<div class="collapsible-header" onclick="toggleCollapsible('serverIncluded')" aria-expanded="false" tabindex="0" role="button" onkeydown="if(event.key==='Enter'||event.key===' '){toggleCollapsible('serverIncluded');event.preventDefault();}">
|
||
<span class="collapsible-toggle" id="serverIncluded-icon"><span class="fa-icon fa-icon-chevron-down" style="--icon-size:12px;"></span></span>
|
||
<span class="collapsible-label">What's Included in Server Management</span>
|
||
</div>
|
||
<div class="collapsible-body" id="serverIncluded">
|
||
<ul class="feature-list">
|
||
<li>RMM monitoring — CPU, RAM, disk, services & event log alerting</li>
|
||
<li>OS patch management — Windows Server updates, tested & scheduled</li>
|
||
<li>Role & service management — AD, DNS, DHCP, file shares, print services</li>
|
||
<li>Performance baselines — capacity planning & proactive alerting</li>
|
||
<li>Backup monitoring — verify, test restores & retention compliance</li>
|
||
<li>Security hardening — CIS benchmarks, local admin control, audit logging</li>
|
||
</ul>
|
||
</div>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ────────────────────────────────────────────────────────────
|
||
SECTION V — ZERO TRUST NETWORKING HaaS
|
||
Starts COLLAPSED. Two independent inputs:
|
||
#ztNetSeats — ZT user seats @ $25/seat/mo (ztNetSeats)
|
||
#ztNetRouters — HaaS router devices @ $100/device/mo (ztNetRouters)
|
||
ztActive = addZT (Sec II checkbox) OR ztSeats > 0
|
||
When ztActive → adds ADMIN_FEE_ZT ($250) to admin fee
|
||
ztNetTotal added to MRR but NOT to baseSubtotal
|
||
#sec05-summary — badge shown when collapsed
|
||
──────────────────────────────────────────────────────────────── -->
|
||
<div class="section" id="sec-05">
|
||
<div class="section-header section-toggle" onclick="toggleSection('sec-05')" aria-expanded="false" tabindex="0" role="button" onkeydown="if(event.key==='Enter'||event.key===' '){toggleSection('sec-05');event.preventDefault();}">
|
||
<div class="section-num">V</div>
|
||
<div class="section-title-block">
|
||
<div class="section-title">Zero Trust Networking <span class="section-title-tag">HaaS</span></div>
|
||
</div>
|
||
<div class="sec-chevron"><span class="fa-icon fa-icon-chevron-down" style="--icon-size:14px;"></span></div>
|
||
<div class="sec-controls-row" onclick="event.stopPropagation()">
|
||
<div class="num-stepper">
|
||
<button class="step-btn" aria-label="Decrease ZT seats" onclick="stepInput('ztNetSeats',-1)">−</button>
|
||
<input class="num-input" id="ztNetSeats" type="number" min="0" value="0" oninput="update()">
|
||
<button class="step-btn" aria-label="Increase ZT seats" onclick="stepInput('ztNetSeats',1)">+</button>
|
||
</div>
|
||
<span class="section-badge">ZT Seats</span>
|
||
<span id="sec05-summary" class="sec-summary-badge"></span>
|
||
</div>
|
||
<div class="section-subtitle">Cytracom-powered ZT network access — seats & managed hardware as a service</div>
|
||
</div>
|
||
<div class="section-body" id="sec-05-body" style="display:none;">
|
||
<div class="section-content">
|
||
|
||
<!-- ZT relationship explainer -->
|
||
<div class="callout-green" style="margin-bottom:20px;">
|
||
<span class="fa-icon fa-icon-square-info fa-icon--accent" style="--icon-size:14px;margin-top:2px;"></span>
|
||
<span><strong>Section II vs Section V — what's the difference?</strong><br>
|
||
Section II's <em>Zero Trust User Seat</em> (+$55/user) adds the ZT software agent to each person's device — identity-aware access, deny-by-default policy, per-user.<br>
|
||
Section V adds <em>ZT network infrastructure</em>: <strong>seats</strong> cover non-user devices (printers, IoT, cameras) that need network access control, and <strong>routers</strong> are the managed ZTNA gateway hardware delivered as a service. Both can be active together.</span>
|
||
</div>
|
||
|
||
<div class="input-row">
|
||
<div>
|
||
<div class="input-label">5B — HaaS Devices</div>
|
||
<div class="input-sublabel">Managed router/firewall hardware · $100/device/mo</div>
|
||
</div>
|
||
<div class="num-stepper">
|
||
<button class="step-btn" aria-label="Decrease ZT routers" onclick="stepInput('ztNetRouters',-1)">−</button>
|
||
<input class="num-input" id="ztNetRouters" type="number" min="0" value="0" oninput="update()">
|
||
<button class="step-btn" aria-label="Increase ZT routers" onclick="stepInput('ztNetRouters',1)">+</button>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ────────────────────────────────────────────────────────────
|
||
SECTION VI — VOIP / UCaaS
|
||
Starts COLLAPSED. Three-tier radio toggle:
|
||
#voipBasic/$28 #voipStandard/$35 #voipPremium/$45
|
||
.tier-seg.active set by activateTier() AND update()
|
||
#voipSeats — seat count input
|
||
#addVoipPhone — Desk Phone HaaS +$15/seat
|
||
#addVoipFax — eFax line +$10/seat/mo
|
||
#currentPhoneBill — optional savings comparator input
|
||
#savingsComparator — green/amber result, rendered by updateSavings()
|
||
voipTotal NOT counted in baseSubtotal (no effect on admin fee)
|
||
#sec06-summary — badge shown when collapsed
|
||
──────────────────────────────────────────────────────────────── -->
|
||
<div class="section" id="sec-06">
|
||
<div class="section-header section-toggle" onclick="toggleSection('sec-06')" aria-expanded="false" tabindex="0" role="button" onkeydown="if(event.key==='Enter'||event.key===' '){toggleSection('sec-06');event.preventDefault();}">
|
||
<div class="section-num">VI</div>
|
||
<div class="section-title-block">
|
||
<div class="section-title">VoIP / Unified Communications <span class="section-title-tag">UCaaS</span></div>
|
||
</div>
|
||
<div class="sec-chevron"><span class="fa-icon fa-icon-chevron-down" style="--icon-size:14px;"></span></div>
|
||
<div class="sec-controls-row" onclick="event.stopPropagation()">
|
||
<div class="num-stepper">
|
||
<button class="step-btn" aria-label="Decrease VoIP seats" onclick="stepInput('voipSeats',-1)">−</button>
|
||
<input class="num-input" id="voipSeats" type="number" min="0" value="0" oninput="update()">
|
||
<button class="step-btn" aria-label="Increase VoIP seats" onclick="stepInput('voipSeats',1)">+</button>
|
||
</div>
|
||
<span class="section-badge">VoIP Seats</span>
|
||
<span id="sec06-summary" class="sec-summary-badge"></span>
|
||
</div>
|
||
<div class="section-subtitle">United Cloud-powered business phone — seats, features & optional desk phones</div>
|
||
</div>
|
||
<div class="section-body" id="sec-06-body" style="display:none;">
|
||
<div class="section-content">
|
||
|
||
<!-- Tier Selector -->
|
||
<div class="tier-seg-wrap">
|
||
<input type="radio" name="voipTier" id="voipBasic" value="basic" checked onchange="update()">
|
||
<label for="voipBasic" class="tier-seg" id="seg-basic" onclick="activateTier('basic')">
|
||
<div class="tier-name">Basic</div>
|
||
<div class="tier-price">$28</div>
|
||
<div class="tier-sub">/seat/mo</div>
|
||
</label>
|
||
<input type="radio" name="voipTier" id="voipStandard" value="standard" onchange="update()">
|
||
<label for="voipStandard" class="tier-seg" id="seg-standard" onclick="activateTier('standard')">
|
||
<div class="tier-name">Standard</div>
|
||
<div class="tier-price">$35</div>
|
||
<div class="tier-sub">/seat/mo</div>
|
||
</label>
|
||
<input type="radio" name="voipTier" id="voipPremium" value="premium" onchange="update()">
|
||
<label for="voipPremium" class="tier-seg" id="seg-premium" onclick="activateTier('premium')">
|
||
<div class="tier-name">Premium</div>
|
||
<div class="tier-price">$45</div>
|
||
<div class="tier-sub">/seat/mo</div>
|
||
</label>
|
||
</div>
|
||
|
||
|
||
<div class="addon-grid" style="margin-top:8px;">
|
||
<label class="addon-row" id="row-vphone" onclick="toggleAddon('addVoipPhone','row-vphone');update()">
|
||
<input type="checkbox" id="addVoipPhone">
|
||
<div><div class="addon-name">Desk Phone HaaS</div><div class="addon-desc">Managed physical desk phone hardware per seat</div></div>
|
||
<span class="addon-price" data-price-key="VOIP_PHONE_RATE" data-price-unit="seat">+$15/seat/mo</span>
|
||
</label>
|
||
<label class="addon-row" id="row-vfax" onclick="toggleAddon('addVoipFax','row-vfax');update()">
|
||
<input type="checkbox" id="addVoipFax">
|
||
<div><div class="addon-name">eFax Line</div><div class="addon-desc">Digital fax number — send & receive via email or portal</div></div>
|
||
<span class="addon-price" data-price-key="VOIP_FAX_RATE" data-price-unit="line">+$10/line/mo</span>
|
||
</label>
|
||
</div>
|
||
|
||
<!-- Phone Bill Savings -->
|
||
<div class="savings-input-row">
|
||
<label for="currentPhoneBill">Current monthly phone bill (optional)</label>
|
||
<input type="number" id="currentPhoneBill" placeholder="$0" min="0"
|
||
oninput="update()" onchange="update()">
|
||
</div>
|
||
<div id="savingsPrompt" class="savings-prompt" style="display:none;">
|
||
Enter your current phone bill above to see potential savings.
|
||
</div>
|
||
<div id="savingsComparator" class="savings-result hidden"></div>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div><!-- END main-col — sections I–VI -->
|
||
|
||
<!-- SIDEBAR -->
|
||
<!-- ── RIGHT COLUMN: sticky sidebar (desktop only ≥1100px) ─────────
|
||
Hidden on mobile via CSS. Mobile clone is injected into #mobilePanelContent.
|
||
nudgeBanner must stay INSIDE .sidebar-body or it gets clipped.
|
||
──────────────────────────────────────────────────────────────── -->
|
||
<div class="side-col">
|
||
<div class="sidebar-focus-backdrop" id="sidebarFocusBackdrop" onclick="closeSidebarFocus()" aria-hidden="true"></div>
|
||
<div class="sidebar-utility">
|
||
<button class="btn-export" onclick="printInvoice()">
|
||
<span class="fa-icon fa-icon-print" style="--icon-size:14px;margin-right:7px;"></span>
|
||
Print / Save PDF
|
||
</button>
|
||
<button class="btn-export btn-export-secondary" id="btnExportJSON" onclick="exportQuoteJSON()">
|
||
<span class="fa-icon fa-icon-file-code" style="--icon-size:14px;margin-right:7px;"></span>
|
||
Export JSON
|
||
</button>
|
||
</div>
|
||
<div class="sidebar">
|
||
<div class="sidebar-header">
|
||
<div class="sidebar-header-row">
|
||
<div class="sidebar-title">SVS MSP — Live Quote</div>
|
||
<button
|
||
type="button"
|
||
class="sidebar-focus-print-btn"
|
||
onclick="printInvoice()"
|
||
aria-label="Print / Save PDF"
|
||
title="Print / Save PDF">
|
||
<span class="fa-icon fa-icon-print" style="--icon-size:14px;margin-right:6px;"></span>
|
||
Print
|
||
</button>
|
||
<button
|
||
type="button"
|
||
class="sidebar-focus-toggle"
|
||
id="sidebarFocusToggle"
|
||
onclick="toggleSidebarFocus()"
|
||
aria-label="Expand live quote"
|
||
aria-pressed="false"
|
||
title="Expand live quote">
|
||
<span class="sidebar-focus-icon sidebar-focus-icon-open">
|
||
<span class="fa-icon fa-icon-up-right-and-down-left-from-center" style="--icon-size:13px;"></span>
|
||
</span>
|
||
<span class="sidebar-focus-icon sidebar-focus-icon-close">
|
||
<span class="fa-icon fa-icon-down-left-and-up-right-to-center" style="--icon-size:13px;"></span>
|
||
</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<!-- ── INSIGHT NUDGE BANNER ──────────────────────────────────────
|
||
Sits flush under .sidebar-header, full width of .sidebar.
|
||
Controlled entirely by renderNudge() via applyNudge("").
|
||
Mobile clone target: #nudgeBanner_m (synced via syncClass/syncEl).
|
||
.hidden class toggled by renderNudge() when nudges=[]
|
||
──────────────────────────────────────────────────────────────── -->
|
||
<div id="nudgeBanner" class="nudge-banner amber hidden">
|
||
<div class="nudge-header-row">
|
||
<span class="nudge-banner-label"><span class="fa-icon fa-icon-lightbulb-on" style="--icon-size:15px;margin-right:6px;"></span> Insight <span id="nudgeCounter" class="nudge-counter"></span></span>
|
||
<div class="nudge-nav-group">
|
||
<button onclick="cycleNudge(-1)" class="nudge-nav-btn" title="Previous"><span class="fa-icon fa-icon-chevron-left"></span></button>
|
||
<button onclick="cycleNudge(1)" class="nudge-nav-btn" title="Next"><span class="fa-icon fa-icon-chevron-right"></span></button>
|
||
</div>
|
||
</div>
|
||
<span id="nudgeText"></span>
|
||
</div>
|
||
<div class="sidebar-body">
|
||
<div class="sidebar-focus-client" id="sidebarFocusClientWrap">
|
||
<span class="sidebar-focus-client-label">Prepared for</span>
|
||
<span class="sidebar-focus-client-name" id="sidebarFocusClientName">Client Name</span>
|
||
</div>
|
||
<div class="sidebar-hero">
|
||
<div class="sidebar-mrr-label">Managed Services Investment (MRI)</div>
|
||
<div class="sidebar-mrr" id="mrrDisplay">$150</div>
|
||
</div>
|
||
|
||
<div class="sidebar-focus-columns">
|
||
<div class="sidebar-focus-col sidebar-focus-col--left">
|
||
<div class="sidebar-group sidebar-group--monthly">
|
||
<div class="sidebar-group-title">Monthly Breakdown</div>
|
||
<!-- ── SIDEBAR SERVICE LINES ────────────────────────────────
|
||
Each .sidebar-line hidden by default.
|
||
update() calls show(id, condition) to toggle .hidden.
|
||
sl-users / sl-endpoints / sl-servers / sl-zt / sl-voip
|
||
shown only when their respective count > 0.
|
||
sl-admin is always visible (never hidden).
|
||
sl-*-sub rows are sub-labels (e.g. "5 × $130/user")
|
||
toggled via style.display not .hidden class.
|
||
────────────────────────────────────────────────────────── -->
|
||
<div id="sidebarLines">
|
||
<div class="sidebar-line hidden" id="sl-users">
|
||
<span><span class="lbl-icon"><span class="fa-icon fa-icon-users" style="--icon-size:14px;"></span></span> Users</span>
|
||
<span class="val" id="sl-users-val">—</span>
|
||
</div>
|
||
<div class="sl-sub hidden" id="sl-users-sub"></div>
|
||
<div class="sidebar-line hidden" id="sl-endpoints">
|
||
<span><span class="lbl-icon"><span class="fa-icon fa-icon-desktop" style="--icon-size:14px;"></span></span> Endpoints</span>
|
||
<span class="val" id="sl-endpoints-val">—</span>
|
||
</div>
|
||
<div class="sl-sub hidden" id="sl-endpoints-sub"></div>
|
||
<div class="sidebar-line hidden" id="sl-servers">
|
||
<span><span class="lbl-icon"><span class="fa-icon fa-icon-server" style="--icon-size:13px;"></span></span> Servers</span>
|
||
<span class="val" id="sl-servers-val">—</span>
|
||
</div>
|
||
<div class="sidebar-line hidden" id="sl-zt">
|
||
<span><span class="lbl-icon"><span class="fa-icon fa-icon-shield-check" style="--icon-size:13px;"></span></span> Zero Trust</span>
|
||
<span class="val" id="sl-zt-val">—</span>
|
||
</div>
|
||
<div class="sidebar-line hidden" id="sl-voip">
|
||
<span><span class="lbl-icon"><span class="fa-icon fa-icon-phone" style="--icon-size:13px;"></span></span> VoIP</span>
|
||
<span class="val" id="sl-voip-val">—</span>
|
||
</div>
|
||
<div class="sidebar-line" id="sl-admin">
|
||
<span><span class="lbl-icon"><span class="fa-icon fa-icon-building" style="--icon-size:12px;"></span></span> Site Management</span>
|
||
<span class="val" id="sl-admin-val">$150</span>
|
||
</div>
|
||
<div class="sl-sub hidden" id="sl-admin-sub"></div>
|
||
</div>
|
||
<div class="sidebar-line sidebar-line-total" id="sl-monthly-total-row">
|
||
<span>Monthly Recurring Total</span>
|
||
<span class="val" id="sl-monthly-total-val">$150</span>
|
||
</div>
|
||
<div class="sidebar-line sidebar-line-discount hidden" id="sl-base-mrr-row">
|
||
<span class="sl-muted">Before Term Incentive</span>
|
||
<span class="val sl-muted" id="sl-base-mrr-val">—</span>
|
||
</div>
|
||
<div class="sidebar-line sidebar-line-discount hidden" id="sl-discount-row">
|
||
<span class="sl-muted">Contract Incentive <span class="sl-discount-detail" id="sl-discount-detail"></span></span>
|
||
<span class="val sl-discount-val" id="sl-discount-val">—</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="sidebar-group sidebar-group--tax">
|
||
<label class="sl-hst-toggle qs-toggle-row">
|
||
<input type="checkbox" id="hstToggle" onchange="update()">
|
||
<span class="qs-switch"></span>
|
||
<span class="qs-toggle-label">Include Tax</span>
|
||
</label>
|
||
<div class="sidebar-line sidebar-line-hst hidden" id="sl-hst-row">
|
||
<span class="sl-muted">+ HST 13%</span>
|
||
<span class="val sl-hst-val" id="sl-hst-val">—</span>
|
||
</div>
|
||
<div class="sidebar-line sidebar-line-total hidden" id="sl-hst-total-row">
|
||
<span>Monthly Total</span>
|
||
<span class="val" id="sl-hst-total-val">—</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="sidebar-focus-col sidebar-focus-col--right">
|
||
<div class="sidebar-group sidebar-group--invoice">
|
||
<div class="sidebar-group-title">First Invoice</div>
|
||
<div class="sidebar-line" id="sl-first-mri-row">
|
||
<span>Invoice Monthly Total</span>
|
||
<span class="val" id="sl-first-mri-val">$150</span>
|
||
</div>
|
||
<div class="sidebar-line hidden" id="sl-first-hst-row">
|
||
<span>+ HST 13%</span>
|
||
<span class="val" id="sl-first-hst-val">—</span>
|
||
</div>
|
||
<div class="sidebar-line hidden" id="sl-otf-row">
|
||
<span>Onboarding / Implementation</span>
|
||
<span class="val" id="sl-otf-val">—</span>
|
||
</div>
|
||
<div class="sidebar-line sidebar-line-total" id="sl-first-total-row">
|
||
<span>First Invoice Total</span>
|
||
<span class="val" id="sl-first-total-val">$150</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="sidebar-group sidebar-group--value">
|
||
<div class="sidebar-group-title">Value & Savings Snapshot</div>
|
||
<div class="sidebar-line hidden sidebar-line-value" id="sl-value-m365-row">
|
||
<span><span class="lbl-icon"><span class="fa-icon fa-icon-square-check fa-icon--green" style="--icon-size:13px;"></span></span>M365 Licensing Savings</span>
|
||
<span class="val savings-amount" id="sl-value-m365-val">—</span>
|
||
</div>
|
||
<div class="sidebar-line hidden sidebar-line-value" id="sl-value-term-row">
|
||
<span><span class="lbl-icon"><span class="fa-icon fa-icon-square-check fa-icon--green" style="--icon-size:13px;"></span></span>Term Incentive Savings</span>
|
||
<span class="val savings-amount" id="sl-value-term-val">—</span>
|
||
</div>
|
||
<div class="sidebar-line hidden sidebar-line-value" id="sl-value-onboarding-row">
|
||
<span><span class="lbl-icon"><span class="fa-icon fa-icon-square-check fa-icon--green" style="--icon-size:13px;"></span></span><span id="sl-value-onboarding-label">Complimentary Onboarding</span></span>
|
||
<span class="val savings-amount" id="sl-value-onboarding-val">—</span>
|
||
</div>
|
||
<div class="sidebar-line hidden sidebar-line-value" id="sl-value-admin-row">
|
||
<span><span class="lbl-icon"><span class="fa-icon fa-icon-square-check fa-icon--green" style="--icon-size:13px;"></span></span>Site Management</span>
|
||
<span class="val savings-amount" id="sl-value-admin-val">—</span>
|
||
</div>
|
||
<div class="sidebar-line hidden sidebar-line-opportunity" id="sl-value-byol-row">
|
||
<span><span class="lbl-icon"><span class="fa-icon fa-icon-triangle-exclamation fa-icon--amber" style="--icon-size:13px;"></span></span>Available M365 Business Premium Value</span>
|
||
<span class="val" id="sl-value-byol-val">—</span>
|
||
</div>
|
||
<div class="sidebar-line sidebar-line-total hidden" id="sl-value-total-row">
|
||
<span>Total Value Unlocked</span>
|
||
<span class="val savings-amount" id="sl-value-total-val">—</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="sidebar-group sidebar-group--summary">
|
||
<div class="sidebar-line">
|
||
<span>Estimated Annual Managed Spend</span>
|
||
<span class="val" id="annualDisplay">$1,800</span>
|
||
</div>
|
||
<div class="sidebar-line hidden" id="perUserRow">
|
||
<span>Effective Managed Cost Per User<br><small id="perUserBreakdown" class="per-user-cost-sub sidebar-note-mono hidden"></small></span>
|
||
<span class="val" id="perUserDisplay">—</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ── VS HIRING IN-HOUSE ─────────────────────────────────────
|
||
Hidden (.hidden) until users>0 OR endpoints>0.
|
||
updateVsComparison(q) renders all values.
|
||
vs-1man-save-row / vs-5man-save-row: background + text colour
|
||
set inline by JS (green = savings, amber = costs more).
|
||
These rows use document.querySelector to reach the
|
||
inner <span> — if the HTML structure changes, update that
|
||
selector in updateVsComparison().
|
||
──────────────────────────────────────────────────────────── -->
|
||
<div id="vsComparison" class="hidden vs-comparison-wrap">
|
||
<div class="vs-header">
|
||
<div class="vs-brand-row">
|
||
<svg width="18" height="24" viewBox="0 0 72 98" class="vs-brand-logo" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
||
<polyline points="7.32 8.88 62.11 8.88 34.72 58.22" fill="#1f75a6"/>
|
||
<polyline points="40.7 55.33 64.4 12.64 71.88 12.64 44.48 61.99 40.7 55.33" fill="#8d252f"/>
|
||
</svg>
|
||
<div class="vs-brand-name">SVS MSP</div>
|
||
</div>
|
||
<div class="vs-label">ROI Snapshot vs. In-House IT</div>
|
||
</div>
|
||
<table class="vs-table">
|
||
<tr>
|
||
<td>
|
||
<span class="vs-svs-label">Managed Services</span>
|
||
</td>
|
||
<td class="vs-val-accent" id="vs-svs-annual">—</td>
|
||
</tr>
|
||
<tr><td class="vs-td-muted"><span class="fa-icon fa-icon-user vs-td-icon" style="--icon-size:13px;"></span> 1 IT person + tools</td><td class="vs-td-muted" id="vs-1man-cost">—</td></tr>
|
||
<tr class="vs-save-row" id="vs-1man-save-row"><td><span id="vs-1man-save-lbl" class="vs-val-green">YOU SAVE</span></td><td id="vs-1man-save" class="vs-val-green">—</td></tr>
|
||
<tr><td class="vs-td-muted"><span class="fa-icon fa-icon-users vs-td-icon" style="--icon-size:14px;"></span> 5-person team</td><td class="vs-td-muted" id="vs-5man-cost">—</td></tr>
|
||
<tr class="vs-save-row" id="vs-5man-save-row"><td><span id="vs-5man-save-lbl" class="vs-val-green">YOU SAVE</span></td><td id="vs-5man-save" class="vs-val-green">—</td></tr>
|
||
</table>
|
||
<div class="vs-footnote" id="vs-footnote"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ── QUOTE NOTES ──────────────────────────────────────────────
|
||
Free-text area for sales rep notes. Persisted in localStorage,
|
||
included in JSON export and printed invoice.
|
||
──────────────────────────────────────────────────────────────── -->
|
||
<div class="quote-notes-wrap">
|
||
<label class="quote-notes-label" for="quoteNotes">Quote Notes</label>
|
||
<textarea class="quote-notes-input" id="quoteNotes" rows="3" placeholder="Additional notes for this quote..." oninput="debouncedSave()"></textarea>
|
||
</div>
|
||
|
||
<!-- ── EXPORT BUTTONS ───────────────────────────────────────────
|
||
Export A: window.print() — triggers browser print/save-as-PDF.
|
||
Export B: exportQuoteJSON() — downloads .json + copies to clipboard.
|
||
exportQuote() — plain-text .txt (original, kept for reference).
|
||
──────────────────────────────────────────────────────────────── -->
|
||
<div class="export-wrap">
|
||
<button type="button" class="btn-reset-quote" onclick="openResetConfirm()">Reset Quote</button>
|
||
<button type="button" class="btn-import-quote" id="btnImportQuote" onclick="importQuoteJSON()">Import Quote</button>
|
||
</div>
|
||
</div><!-- END sidebar-body -->
|
||
</div><!-- END sidebar -->
|
||
</div><!-- END side-col — desktop sidebar -->
|
||
|
||
</div><!-- END outer grid (3fr main-col / 2fr side-col) -->
|
||
|
||
<!-- BOTTOM PITCH -->
|
||
<div class="pitch-wrap">
|
||
<div class="pitch-inner">
|
||
<div class="pitch-grid">
|
||
<div class="pitch-item">
|
||
<div class="pitch-head">
|
||
<div class="pitch-icon"><span class="fa-icon fa-icon-shield-check fa-icon--accent" style="--icon-size:20px;"></span></div>
|
||
<div class="pitch-title">Security-First MSP</div>
|
||
</div>
|
||
<div class="pitch-desc">Every engagement is built on a security baseline — EDR, MFA, patch management, and cyber warranty included.</div>
|
||
</div>
|
||
<div class="pitch-item">
|
||
<div class="pitch-head">
|
||
<div class="pitch-icon"><span class="fa-icon fa-icon-location-dot fa-icon--accent" style="--icon-size:20px;"></span></div>
|
||
<div class="pitch-title">Ottawa-Based Team</div>
|
||
</div>
|
||
<div class="pitch-desc">Local presence, Canadian data sovereignty, and an account team that knows your business and your region.</div>
|
||
</div>
|
||
<div class="pitch-item">
|
||
<div class="pitch-head">
|
||
<div class="pitch-icon"><span class="fa-icon fa-icon-wrench-simple fa-icon--accent" style="--icon-size:20px;"></span></div>
|
||
<div class="pitch-title">Flat-Rate, No Surprises</div>
|
||
</div>
|
||
<div class="pitch-desc">Predictable monthly billing with no per-ticket charges — aligned incentives mean we fix things right the first time.</div>
|
||
</div>
|
||
<div class="pitch-item">
|
||
<div class="pitch-head">
|
||
<div class="pitch-icon"><span class="fa-icon fa-icon-chart-line-up fa-icon--accent" style="--icon-size:20px;"></span></div>
|
||
<div class="pitch-title">Scales With You</div>
|
||
</div>
|
||
<div class="pitch-desc">Add users, endpoints, servers, ZT networking, or VoIP as you grow — one vendor, one invoice, one relationship.</div>
|
||
</div>
|
||
</div>
|
||
<div class="pitch-footer">
|
||
<span class="fa-icon fa-icon-square-check" style="--icon-size:13px;margin-right:5px;"></span> Canadian company, Canadian support
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<div class="confirm-modal" id="resetConfirmModal" aria-hidden="true">
|
||
<div class="confirm-modal-backdrop" onclick="closeResetConfirm()"></div>
|
||
<div class="confirm-modal-card" role="dialog" aria-modal="true" aria-labelledby="resetConfirmTitle">
|
||
<div class="confirm-modal-eyebrow">Reset Quote</div>
|
||
<h2 class="confirm-modal-title" id="resetConfirmTitle">Reset saved quote and return to defaults?</h2>
|
||
<p class="confirm-modal-copy">This will clear the saved calculator state and generate a fresh quote. Your theme preference will stay the same.</p>
|
||
<div class="confirm-modal-actions">
|
||
<button type="button" class="confirm-btn confirm-btn-secondary" id="resetConfirmCancel" onclick="closeResetConfirm()">Cancel</button>
|
||
<button type="button" class="confirm-btn confirm-btn-danger" onclick="confirmResetQuote()">Yes, Reset</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="package-prices-data.js"></script>
|
||
<script src="quote-pricing.js"></script>
|
||
<script src="quote-engine.js"></script>
|
||
<script src="quote-render.js"></script>
|
||
<script src="quote-persistence.js"></script>
|
||
<script src="quote-export.js"></script>
|
||
<script src="quote-import.js"></script>
|
||
<script src="theme-manager.js"></script>
|
||
<script src="SVS-MSP-Calculator.js"></script>
|
||
<script src="mobile-sync.js"></script>
|
||
</body>
|
||
</html>
|
||
|