Light & Dark Theme Alterations
This commit is contained in:
@@ -7,14 +7,14 @@
|
||||
|
||||
/* ── DESIGN TOKENS (light overrides) ───────────────────────────── */
|
||||
:root {
|
||||
--ink: #1a1816; /* near-black for body text */
|
||||
--paper: #f4f2ed; /* warm off-white page background */
|
||||
--accent: #1a6a98; /* slightly darker blue for contrast */
|
||||
--muted: #6b6360; /* mid-grey for secondary text */
|
||||
--border: #ccc9c3; /* light grey borders */
|
||||
--card: #ebe8e2; /* off-white card background */
|
||||
--green: #217045; /* darker green — accessible on white */
|
||||
--amber: #a05f00; /* darker amber — accessible on white */
|
||||
--ink: #2c2825; /* soft near-black — readable without harshness */
|
||||
--paper: #f4f2ed; /* warm off-white page background */
|
||||
--accent: #1a6a98; /* blue — good for buttons, kept full strength */
|
||||
--muted: #6b6360; /* mid-grey for secondary text */
|
||||
--border: #d0cdc7; /* soft warm-grey borders */
|
||||
--card: #ebe8e2; /* off-white card background */
|
||||
--green: #217045; /* darker green — accessible on white */
|
||||
--amber: #a05f00; /* darker amber — accessible on white */
|
||||
}
|
||||
|
||||
/* ── BODY ────────────────────────────────────────────────────────── */
|
||||
@@ -30,11 +30,12 @@ body {
|
||||
─────────────────────────────────────────────────────────────────── */
|
||||
.top-bar {
|
||||
background: #e8e4db !important;
|
||||
border-bottom-color: rgba(0, 0, 0, 0.09) !important; /* replace strong blue stripe with soft warm separator */
|
||||
}
|
||||
|
||||
/* ── SECTION CARDS ───────────────────────────────────────────────── */
|
||||
.section {
|
||||
background: #ffffff !important;
|
||||
background: #faf9f5 !important; /* warm white — less stark than pure white on cream background */
|
||||
}
|
||||
|
||||
/* ── CHEVRON PILL — swap white-alpha tint for dark-alpha ─────────── */
|
||||
@@ -48,12 +49,12 @@ body {
|
||||
|
||||
/* ── SECTION HOVER / OPEN GLOW ───────────────────────────────────── */
|
||||
.section:hover {
|
||||
border-color: rgba(26, 106, 152, 0.3) !important;
|
||||
box-shadow: -3px 0 0 0 rgba(26, 106, 152, 0.35) !important;
|
||||
border-color: rgba(26, 106, 152, 0.22) !important;
|
||||
box-shadow: -3px 0 0 0 rgba(26, 106, 152, 0.25) !important;
|
||||
}
|
||||
.sec-open {
|
||||
border-color: rgba(26, 106, 152, 0.45) !important;
|
||||
box-shadow: -3px 0 0 0 rgba(26, 106, 152, 0.65) !important;
|
||||
border-color: rgba(26, 106, 152, 0.35) !important;
|
||||
box-shadow: -3px 0 0 0 rgba(26, 106, 152, 0.45) !important;
|
||||
}
|
||||
|
||||
/* ── CALLOUT BOXES ───────────────────────────────────────────────── */
|
||||
@@ -78,7 +79,12 @@ body {
|
||||
color: var(--ink) !important;
|
||||
}
|
||||
.addon-row.selected .addon-price {
|
||||
color: var(--accent) !important;
|
||||
color: var(--accent) !important; /* override dark-mode #62c5f0 */
|
||||
}
|
||||
|
||||
/* ── FEATURE CARDS ───────────────────────────────────────────────── */
|
||||
.feature-card {
|
||||
background: #f0ede7 !important;
|
||||
}
|
||||
|
||||
/* ── NUDGE BANNER ────────────────────────────────────────────────── */
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
--ink: #ddd8d0;
|
||||
--paper: #22201d;
|
||||
--accent: #2d7aa8;
|
||||
--muted: #a09890;
|
||||
--muted: #b0a898; /* lifted slightly — #a09890 was too faint on dark cards */
|
||||
--border: #3a3630;
|
||||
--card: #2a2722;
|
||||
--green: #3ab870;
|
||||
@@ -166,7 +166,7 @@
|
||||
margin-left: 96px;
|
||||
border-radius: 12px;
|
||||
border: 1px solid var(--border);
|
||||
background: #1e1c18;
|
||||
background: #272420; /* elevated above paper #22201d — was #1e1c18 (sunken) */
|
||||
padding: 32px 36px 36px;
|
||||
}
|
||||
.main-col > .section:first-of-type { margin-top: 24px; }
|
||||
@@ -555,8 +555,8 @@
|
||||
first line; text wrapped in <span> so it never flows under icon.
|
||||
─────────────────────────────────────────────────────────────── */
|
||||
.callout-green {
|
||||
background: #0d2016;
|
||||
border: 1px solid #1e4a30;
|
||||
background: #162e22; /* dark muted green — was #0d2016 (near-black, unreadable as green) */
|
||||
border: 1px solid #245840;
|
||||
border-radius: 6px;
|
||||
padding: 14px 18px;
|
||||
font-family: 'DM Mono', monospace;
|
||||
@@ -569,13 +569,13 @@
|
||||
gap: 9px;
|
||||
}
|
||||
.callout-red {
|
||||
background: #200d10;
|
||||
border: 1px solid #4a1e24;
|
||||
background: #2a1319; /* dark muted red — was #200d10 (near-black) */
|
||||
border: 1px solid #5e2830;
|
||||
border-radius: 6px;
|
||||
padding: 14px 18px;
|
||||
font-family: 'DM Mono', monospace;
|
||||
font-size: 14px;
|
||||
color: #e06070;
|
||||
color: #e87882; /* slightly lighter than #e06070 for better contrast on dark red bg */
|
||||
margin-bottom: 24px;
|
||||
line-height: 1.65;
|
||||
display: flex;
|
||||
@@ -775,13 +775,13 @@
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.nudge-banner.amber {
|
||||
background: #1f1500;
|
||||
color: #d4901a;
|
||||
background: #2a1e06; /* warm amber-tinted dark — was #1f1500 (near-black) */
|
||||
color: var(--amber); /* use token — was hardcoded #d4901a */
|
||||
border-left: 3px solid var(--amber);
|
||||
}
|
||||
.nudge-banner.green {
|
||||
background: #1a2e20;
|
||||
color: #3dc472;
|
||||
background: #162e22; /* match callout-green — was #1a2e20 */
|
||||
color: var(--green); /* use token — was off-token #3dc472 */
|
||||
border-left: 3px solid var(--green);
|
||||
}
|
||||
.nudge-banner-label {
|
||||
@@ -1224,8 +1224,8 @@
|
||||
}
|
||||
.savings-result {
|
||||
margin-top: 12px;
|
||||
background: #0d2016;
|
||||
border: 1px solid #1e4a30;
|
||||
background: #162e22; /* match callout-green — was #0d2016 (near-black) */
|
||||
border: 1px solid #245840;
|
||||
border-radius: 6px;
|
||||
padding: 12px 16px;
|
||||
font-family: 'DM Mono', monospace;
|
||||
@@ -1267,8 +1267,8 @@
|
||||
.pitch-title { font-family: 'Poppins', sans-serif; font-weight: 600; font-size: 16px; margin-bottom: 8px; }
|
||||
.pitch-desc { font-size: 14px; color: var(--muted); line-height: 1.7; }
|
||||
.pitch-footer {
|
||||
background: #1a2e20;
|
||||
border-top: 1px solid #1e4a30;
|
||||
background: #162e22; /* match green callout family — was #1a2e20 */
|
||||
border-top: 1px solid #245840;
|
||||
padding: 16px 32px;
|
||||
font-family: 'DM Mono', monospace;
|
||||
font-size: 13px;
|
||||
@@ -1299,12 +1299,31 @@
|
||||
/* ═══════════════════════════════════════════════════════
|
||||
RESPONSIVE — MOBILE FIRST
|
||||
Breakpoints:
|
||||
< 600px — phone portrait
|
||||
600–900px — phone landscape / small tablet
|
||||
< 600px — phone portrait
|
||||
600–900px — phone landscape / small tablet
|
||||
900–1100px — tablet portrait
|
||||
> 1100px — desktop (base styles apply)
|
||||
1101–1350px — narrow desktop (2-col, tighter numerals)
|
||||
> 1350px — desktop (base styles apply)
|
||||
═══════════════════════════════════════════════════════ */
|
||||
|
||||
/* ── NARROW DESKTOP (≤ 1350px, > 1100px) ─────────────────────
|
||||
Reduces the section numeral gutter and outer gap to give the
|
||||
content columns more breathing room on small laptops / narrow
|
||||
monitors before the layout collapses to single-column at 1100px.
|
||||
─────────────────────────────────────────────────────────────── */
|
||||
@media (max-width: 1350px) {
|
||||
.outer {
|
||||
gap: 36px;
|
||||
padding: 52px clamp(48px,4vw,60px) 52px;
|
||||
}
|
||||
.section { margin-left: 76px; }
|
||||
.section-num { left: -76px; width: 64px; font-size: 54px; top: 30px; }
|
||||
.client-bar { padding: 32px 0 32px 76px; }
|
||||
.quote-settings-bar { margin-left: 76px; }
|
||||
.sections-toolbar { margin-left: 76px; }
|
||||
.top-bar-logo { margin-left: 50px; }
|
||||
}
|
||||
|
||||
/* ── TABLET PORTRAIT (≤ 1100px) ── */
|
||||
@media (max-width: 1100px) {
|
||||
.outer {
|
||||
|
||||
@@ -275,7 +275,7 @@
|
||||
</div>
|
||||
|
||||
<div class="sections-toolbar">
|
||||
<button class="btn-toggle-all" id="toggleAllBtn" onclick="toggleAllSections()">Collapse All</button>
|
||||
<button class="btn-toggle-all" id="toggleAllBtn" onclick="toggleAllSections()"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="11" height="11" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:middle;margin-right:5px;"><polyline points="6 9 12 15 18 9"/><polyline points="6 15 12 9 18 15"/></svg>Collapse All</button>
|
||||
</div>
|
||||
|
||||
<!-- ────────────────────────────────────────────────────────────
|
||||
@@ -635,6 +635,10 @@
|
||||
<div class="section-title">Zero Trust Networking <span class="section-title-tag">HaaS</span></div>
|
||||
<div class="section-subtitle">Cytracom-powered ZT network access — seats & managed hardware as a service</div>
|
||||
<span class="section-badge">Per User + Per Device / Month</span>
|
||||
<div class="sec-collapsed-counter">
|
||||
<button class="sec-count-btn" onclick="stepCount('ztNetSeats',-1,event)">−</button>
|
||||
<button class="sec-count-btn" onclick="stepCount('ztNetSeats',1,event)">+</button>
|
||||
</div>
|
||||
</div>
|
||||
<span id="sec05-summary" class="sec-summary-badge"></span>
|
||||
<div class="sec-chevron"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg></div>
|
||||
@@ -755,7 +759,7 @@
|
||||
<div class="savings-input-row">
|
||||
<label for="currentPhoneBill">Current monthly phone bill (optional)</label>
|
||||
<input type="number" id="currentPhoneBill" placeholder="$0" min="0"
|
||||
oninput="updateSavings()" onchange="updateSavings()">
|
||||
oninput="update()" onchange="update()">
|
||||
</div>
|
||||
<div id="savingsPrompt" class="savings-prompt" style="display:none;">
|
||||
Enter your current phone bill above to see potential savings.
|
||||
@@ -961,7 +965,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="pitch-footer">
|
||||
✓ No lock-in contracts on standard plans · ✓ Onboarding included · ✓ Canadian company, Canadian support
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="13" height="13" fill="currentColor" style="vertical-align:middle;margin-right:5px;flex-shrink:0;"><path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM369 209L241 337c-9.4 9.4-24.6 9.4-33.9 0l-64-64c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l47 47L335 175c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9z"/></svg> Canadian company, Canadian support
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -179,7 +179,7 @@ function calcQuote() {
|
||||
|
||||
return {
|
||||
users, endpoints, servers, ztSeats, ztRouters, voipSeats, voipTier, addVoipPhone, addVoipFax,
|
||||
byol, addPWM, addINKY, addExtHours, addZT, addUSB, addBMB, ztActive, clientName,
|
||||
byol, addPWM, addINKY, addExtHours, addZT, addUSB, addBMB, ztActive, adminWaived, clientName,
|
||||
contractTerm, hstEnabled, oneTimeFee,
|
||||
baseUserRate, totalUserRate,
|
||||
userBase, userPWM, userINKY, userExt, userZT, userTotal,
|
||||
@@ -238,7 +238,7 @@ function update() {
|
||||
q.oneTimeFee = oneTimeFee;
|
||||
|
||||
const { users, endpoints, servers, voipSeats, voipTier,
|
||||
byol, addPWM, addINKY, addExtHours, addZT, addUSB, addBMB, ztActive, clientName,
|
||||
byol, addPWM, addINKY, addExtHours, addZT, addUSB, addBMB, ztActive, adminWaived, clientName,
|
||||
contractTerm, hstEnabled,
|
||||
baseUserRate,
|
||||
userPWM, userINKY, userExt, userZT, userTotal,
|
||||
@@ -513,7 +513,9 @@ function toggleAllSections() {
|
||||
function updateToggleAllBtn() {
|
||||
const anyOpen = _allSecIds.some(id => document.getElementById(id)?.classList.contains('sec-open'));
|
||||
const btn = document.getElementById('toggleAllBtn');
|
||||
if (btn) btn.textContent = anyOpen ? 'Collapse All' : 'Expand All';
|
||||
const collapseIcon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="11" height="11" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:middle;margin-right:5px;"><polyline points="6 9 12 15 18 9"/><polyline points="6 15 12 9 18 15"/></svg>';
|
||||
const expandIcon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="11" height="11" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:middle;margin-right:5px;"><polyline points="6 15 12 9 18 15"/><polyline points="6 9 12 15 18 9"/></svg>';
|
||||
if (btn) btn.innerHTML = anyOpen ? collapseIcon + 'Collapse All' : expandIcon + 'Expand All';
|
||||
}
|
||||
|
||||
// ── stepCount(inputId, delta, event) ─────────────────────────────
|
||||
@@ -642,7 +644,10 @@ function updateVsComparison(q) {
|
||||
applyVsRow('vs-1man-save-row', 'vs-1man-save', 'vs-1man-save-lbl', save1);
|
||||
applyVsRow('vs-5man-save-row', 'vs-5man-save', 'vs-5man-save-lbl', save5);
|
||||
|
||||
getEl('vs-footnote').textContent = `Based on ~$85K Ottawa IT salary (2024) + min $650/mo tool licensing (M365, EDR, RMM, backup, SAT & more). No benefits, hiring, or turnover costs factored.`;
|
||||
const toolsLabel = toolsMonthly <= TOOL_COST_MIN
|
||||
? `min $${TOOL_COST_MIN}/mo`
|
||||
: `~$${toolsMonthly}/mo`;
|
||||
getEl('vs-footnote').textContent = `Based on ~$85K Ottawa IT salary (2024) + ${toolsLabel} tool licensing (M365, EDR, RMM, backup, SAT & more). No benefits, hiring, or turnover costs factored.`;
|
||||
}
|
||||
|
||||
// ── renderNudge() ─────────────────────────────────────────────────
|
||||
@@ -1062,9 +1067,9 @@ function exportQuoteJSON() {
|
||||
navigator.clipboard?.writeText(json).then(() => {
|
||||
const btn = document.getElementById('btnExportJSON');
|
||||
if (btn) {
|
||||
const orig = btn.textContent;
|
||||
btn.textContent = '✓ Copied to clipboard';
|
||||
setTimeout(() => { btn.textContent = orig; }, 2000);
|
||||
const orig = btn.innerHTML;
|
||||
btn.innerHTML = '✓ Copied to clipboard';
|
||||
setTimeout(() => { btn.innerHTML = orig; }, 2000);
|
||||
}
|
||||
}).catch(() => {});
|
||||
}
|
||||
@@ -1128,8 +1133,22 @@ async function initQuote() {
|
||||
const month = months[now.getMonth()];
|
||||
const dateStr = `${year}${String(now.getMonth()+1).padStart(2,'0')}${String(now.getDate()).padStart(2,'0')}`;
|
||||
const savedRef = localStorage.getItem('svs-msp-quote-ref');
|
||||
const quoteRef = savedRef || `SVS-${dateStr}-${String(Math.floor(Math.random()*9000)+1000)}`;
|
||||
if (!savedRef) localStorage.setItem('svs-msp-quote-ref', quoteRef);
|
||||
let quoteRef;
|
||||
if (savedRef) {
|
||||
// Regenerate if the baked-in date is older than 30 days
|
||||
const m = savedRef.match(/^SVS-(\d{4})(\d{2})(\d{2})-/);
|
||||
const refDate = m ? new Date(+m[1], +m[2] - 1, +m[3]) : null;
|
||||
const ageMs = refDate ? now - refDate : Infinity;
|
||||
if (ageMs > 30 * 24 * 60 * 60 * 1000) {
|
||||
quoteRef = `SVS-${dateStr}-${String(Math.floor(Math.random()*9000)+1000)}`;
|
||||
localStorage.setItem('svs-msp-quote-ref', quoteRef);
|
||||
} else {
|
||||
quoteRef = savedRef;
|
||||
}
|
||||
} else {
|
||||
quoteRef = `SVS-${dateStr}-${String(Math.floor(Math.random()*9000)+1000)}`;
|
||||
localStorage.setItem('svs-msp-quote-ref', quoteRef);
|
||||
}
|
||||
document.getElementById('quoteRef').textContent = quoteRef;
|
||||
document.getElementById('headerDate').textContent = `${month} ${year}`;
|
||||
restoreState();
|
||||
|
||||
Reference in New Issue
Block a user