Light & Dark Theme Alterations

This commit is contained in:
John OReilly
2026-03-12 00:47:18 -04:00
parent 901b3bb116
commit 1663c69c63
4 changed files with 92 additions and 44 deletions

View File

@@ -7,11 +7,11 @@
/* ── DESIGN TOKENS (light overrides) ───────────────────────────── */
:root {
--ink: #1a1816; /* near-black for body text */
--ink: #2c2825; /* soft near-black — readable without harshness */
--paper: #f4f2ed; /* warm off-white page background */
--accent: #1a6a98; /* slightly darker blue for contrast */
--accent: #1a6a98; /* blue — good for buttons, kept full strength */
--muted: #6b6360; /* mid-grey for secondary text */
--border: #ccc9c3; /* light grey borders */
--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 */
@@ -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 ────────────────────────────────────────────────── */

View File

@@ -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;
@@ -1302,9 +1302,28 @@
< 600px — phone portrait
600900px — phone landscape / small tablet
9001100px — tablet portrait
> 1100px — desktop (base styles apply)
11011350px — 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 {

View File

@@ -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 &amp; 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)">&minus;</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 &nbsp;·&nbsp; ✓ Onboarding included &nbsp;·&nbsp; 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>

View File

@@ -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();