diff --git a/M365icons/azure-svgrepo-com.svg b/M365icons/azure-svgrepo-com.svg new file mode 100644 index 0000000..bfeff67 --- /dev/null +++ b/M365icons/azure-svgrepo-com.svg @@ -0,0 +1,2 @@ + +file_type_azure \ No newline at end of file diff --git a/M365icons/excel.svg b/M365icons/excel.svg new file mode 100644 index 0000000..d952563 --- /dev/null +++ b/M365icons/excel.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/M365icons/excel2-svgrepo-com.svg b/M365icons/excel2-svgrepo-com.svg new file mode 100644 index 0000000..5d973e9 --- /dev/null +++ b/M365icons/excel2-svgrepo-com.svg @@ -0,0 +1,2 @@ + +file_type_excel2 \ No newline at end of file diff --git a/M365icons/outlook-svgrepo-com.svg b/M365icons/outlook-svgrepo-com.svg new file mode 100644 index 0000000..209390d --- /dev/null +++ b/M365icons/outlook-svgrepo-com.svg @@ -0,0 +1,2 @@ + +file_type_outlook \ No newline at end of file diff --git a/M365icons/powerpoint.svg b/M365icons/powerpoint.svg new file mode 100644 index 0000000..766e909 --- /dev/null +++ b/M365icons/powerpoint.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/M365icons/teams.svg b/M365icons/teams.svg new file mode 100644 index 0000000..d3cf515 --- /dev/null +++ b/M365icons/teams.svg @@ -0,0 +1,21 @@ + + + + + + + + + \ No newline at end of file diff --git a/M365icons/word.svg b/M365icons/word.svg new file mode 100644 index 0000000..0876ec8 --- /dev/null +++ b/M365icons/word.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/SVS-MSP-Calculator-70retro.css b/SVS-MSP-Calculator-70retro.css new file mode 100644 index 0000000..34b7361 --- /dev/null +++ b/SVS-MSP-Calculator-70retro.css @@ -0,0 +1,282 @@ +/* ══════════════════════════════════════════════════════════════ + SVS MSP Calculator — Retro Cyberpunk Theme + Warm parchment paper base with neon-warm accents — + hot rose highlights, electric amber secondary, warm teal pop, + dark charcoal header. Vintage paper meets neon signage. + ══════════════════════════════════════════════════════════════ */ + +:root { + /* ── Core palette ────────────────────────────────────────── */ + --ink: #1c1317; + --paper: #f0e4c8; + --accent: #e11d48; + --muted: #8a7a72; + --border: #d0c4b0; + --border-soft: #d8ccb8; + --card: #e8dcc0; + --green: #0d9488; + --amber: #d97706; + --sky: #0d9488; + --focus-ring-soft: rgba(225, 29, 72, 0.2); + + /* ── Top bar ─────────────────────────────────────────────── */ + --top-bar-bg: #1c1317; + --top-bar-border: rgba(225, 29, 72, 0.35); + --top-bar-meta: #c0aa98; + --top-bar-shadow: 0 4px 16px rgba(28, 19, 23, 0.2); + + /* ── Theme chip ──────────────────────────────────────────── */ + --theme-chip-bg: rgba(225, 29, 72, 0.1); + --theme-chip-hover: rgba(225, 29, 72, 0.18); + --theme-chip-active: rgba(225, 29, 72, 0.26); + --theme-chip-fg: #f0e4d0; + + /* ── Surfaces ────────────────────────────────────────────── */ + --surface-section: #e4d5b5; + --surface-feature: #dccda8; + --surface-settings: #d6c49e; + --surface-settings-divider: #c4ae8a; + --surface-input: #efe2c4; + --surface-term-wrap: #e0d0ad; + --surface-term-tile: transparent; + --surface-term-tile-hover: rgba(225, 29, 72, 0.05); + --surface-term-tile-active: linear-gradient(180deg, #e11d48 0%, #be123c 100%); + --border-term-wrap: #c4ae8a; + --border-term-tile-active: rgba(225, 29, 72, 0.3); + --shadow-term-wrap: inset 0 1px 0 rgba(255, 255, 255, 0.3); + --shadow-term-tile-active: inset 0 1px 0 rgba(255, 255, 255, 0.2); + + /* ── Term text ───────────────────────────────────────────── */ + --text-term-name: #8a7a72; + --text-term-sub: #6a5a50; + --text-term-sub-active: #fff; + --text-term-name-active: #fff; + --text-term-discount: #1c1317; + --text-term-discount-active: #ffffff; + + /* ── Best value badge ────────────────────────────────────── */ + --surface-best-value: rgba(13, 148, 136, 0.12); + --border-best-value: rgba(13, 148, 136, 0.32); + --text-best-value: #0d9488; + --surface-best-value-active: rgba(255, 255, 255, 0.2); + --border-best-value-active: rgba(255, 255, 255, 0.4); + --text-best-value-active: #ffffff; + + /* ── Sidebar ─────────────────────────────────────────────── */ + --surface-sidebar: #e0d4b6; + --surface-sidebar-header: #1c1317; + --surface-sidebar-body: #e6d8b8; + --surface-sidebar-utility: #d0be98; + --surface-export: #ccba94; + --border-sidebar: #c4ae8a; + --surface-sidebar-utility-border: #b5a07a; + --border-export-top: #c4ae8a; + + /* ── Compare / Modal ─────────────────────────────────────── */ + --surface-compare: #d6c8a6; + --border-compare: #c4ae8a; + --surface-modal: #efe2c4; + --surface-backdrop: rgba(28, 19, 23, 0.6); + --shadow-modal: 0 16px 50px rgba(28, 19, 23, 0.35); + + /* ── Mobile ──────────────────────────────────────────────── */ + --surface-mobile-sheet: #e4d5b5; + --surface-mobile-close-row: #d6c49e; + --surface-mobile-actions: #d6c49e; + --surface-mobile-sidebar: transparent; + --surface-mobile-close-btn: rgba(28, 19, 23, 0.08); + --surface-mobile-close-btn-active: rgba(28, 19, 23, 0.14); + --border-mobile-sheet: #c4ae8a; + --border-mobile-row: #c4ae8a; + + /* ── Ghost / Utility surfaces ────────────────────────────── */ + --surface-accent-soft: rgba(225, 29, 72, 0.05); + --surface-summary-badge: rgba(225, 29, 72, 0.08); + --border-summary-badge: rgba(225, 29, 72, 0.2); + --surface-chevron: rgba(28, 19, 23, 0.05); + --surface-chevron-active: rgba(28, 19, 23, 0.09); + --surface-ghost: rgba(28, 19, 23, 0.06); + --surface-ghost-hover: rgba(28, 19, 23, 0.12); + --surface-step: #efe2c4; + --surface-step-hover: #d6c49e; + --surface-step-active: var(--accent); + --surface-step-border: #b5a07a; + --text-step: var(--accent); + + /* ── State surfaces ──────────────────────────────────────── */ + --surface-success: #dceee6; + --surface-success-border: #6db89a; + --surface-danger: #f5dcd6; + --surface-danger-border: #d4827a; + --text-danger: #b91c1c; + --surface-warning: #f0e4c4; + --surface-warning-panel: #ecdcb8; + --surface-warning-border: #d4a860; + --surface-compare-success: rgba(13, 148, 136, 0.12); + --surface-compare-warning: rgba(217, 119, 6, 0.12); + --surface-selected: rgba(225, 29, 72, 0.06); + --surface-addon-hover: rgba(225, 29, 72, 0.04); + --border-addon-hover: rgba(225, 29, 72, 0.18); + --text-selected-accent: #9f1239; + + /* ── Text colours ────────────────────────────────────────── */ + --text-sidebar-kicker: rgba(255, 255, 255, 0.84); + --text-sidebar-heading: #fff; + --text-sidebar-placeholder: rgba(255, 255, 255, 0.72); + --text-money: var(--ink); + --text-money-hero: var(--ink); + --text-vs-heading: var(--ink); + --text-vs-accent: #be123c; + --text-vs-muted: var(--muted); + --text-incentive: #0d9488; + --text-pill-savings-active: #ccfbf1; + + /* ── Section interaction ─────────────────────────────────── */ + --section-hover-border: rgba(225, 29, 72, 0.18); + --section-hover-shadow: -3px 0 0 0 rgba(225, 29, 72, 0.2); + --section-open-border: rgba(225, 29, 72, 0.3); + --section-open-shadow: -3px 0 0 0 rgba(225, 29, 72, 0.35); + + /* ── Buttons ─────────────────────────────────────────────── */ + --btn-primary-fg: #ffffff; + --btn-primary-hover: #be123c; + --surface-pill-icon: rgba(255, 255, 255, 0.2); + --sidebar-zone-services: rgba(0, 0, 0, 0.03); + --sidebar-zone-invoice: rgba(0, 0, 0, 0.045); + --sidebar-zone-value: rgba(0, 0, 0, 0.02); + --surface-switch-off: #c0b4a0; + --surface-switch-on: var(--green); +} + +/* ── Retro cyberpunk typography ───────────────────────────── */ +.top-bar, +.section-header .section-title, +.sidebar-header, +.sidebar-mrr, +.sidebar-hero-label { + font-family: 'Poppins', sans-serif; + letter-spacing: 0.04em; +} + +/* ── Top bar — warm dark with hot rose neon edge ─────────── */ +.top-bar { + background: linear-gradient(180deg, #2a1e22 0%, #1c1317 60%, #140e11 100%) !important; + border-bottom: 1px solid rgba(225, 29, 72, 0.3) !important; + box-shadow: 0 2px 16px rgba(225, 29, 72, 0.06) !important; + color: #f0e4d0 !important; +} +.top-bar .top-bar-meta { color: #c0aa98 !important; } + +/* ── Logo fix — SVG text paths hardcoded #0c0c0c, + override to cream so they pop on the dark header ─────── */ +.top-bar-logo path { + fill: #f0e4d0 !important; +} + +/* ── Sidebar header — matches top bar ────────────────────── */ +.sidebar-header { + background: linear-gradient(180deg, #2a1e22 0%, #1c1317 100%) !important; + color: #fff !important; +} + +/* ── Section number — hot rose (faded on paper) ──────────── */ +.section-num { + color: rgba(225, 29, 72, 0.15) !important; +} + +/* ── Pill toggle checked — hot rose gradient ─────────────── */ +.pill-toggle input:checked + label { + background: linear-gradient(180deg, #e11d48 0%, #be123c 100%) !important; + color: #fff !important; +} +.pill-toggle input:checked + label .pill-price, +.pill-toggle input:checked + label .pill-desc { + color: #fff !important; +} + +/* ── Export buttons — hot rose CTA ───────────────────────── */ +.btn-export { + background: linear-gradient(180deg, #e11d48 0%, #be123c 100%) !important; + color: #fff !important; +} +.btn-export:hover { + filter: brightness(1.1) !important; + box-shadow: 0 2px 12px rgba(225, 29, 72, 0.3) !important; +} + +/* ── Tier segment active — hot rose gradient ─────────────── */ +.tier-seg.active { + background: linear-gradient(180deg, #e11d48 0%, #be123c 100%) !important; + color: #fff !important; +} + +/* ── Import button hover — teal accent ───────────────────── */ +.btn-import-quote:hover { + background: color-mix(in srgb, var(--sky) 8%, transparent); + border-color: color-mix(in srgb, var(--sky) 30%, transparent); + color: var(--sky); +} + +/* ── Addon selected — rose tint on paper ─────────────────── */ +.addon-row.selected { + background: rgba(225, 29, 72, 0.04) !important; + border-color: rgba(225, 29, 72, 0.18) !important; + box-shadow: inset 3px 0 0 0 var(--accent) !important; +} + +/* ── Paper texture with warm scanlines ───────────────────── */ +body { + background-color: #f0e4c8; + background-image: + repeating-linear-gradient( + 0deg, + transparent, + transparent 2px, + rgba(180, 150, 100, 0.03) 2px, + rgba(180, 150, 100, 0.03) 4px + ); +} + +/* ── Switch knob — hot rose when active ──────────────────── */ +.switch input:checked + .switch-track { + background: var(--accent) !important; +} + +/* ── Nudge banners — warm paper tints ────────────────────── */ +.nudge-banner.amber { + background: #f0dab0 !important; + border-color: #d4a040 !important; +} +.nudge-banner.green { + background: #d6ece4 !important; + border-color: #5aaa98 !important; +} + +/* ── Callout boxes ───────────────────────────────────────── */ +.callout-green { + background: #dceee6 !important; + border-color: #6db89a !important; + color: #0d9488 !important; +} +.callout-red { + background: #f5dcd6 !important; + border-color: #d4827a !important; +} + +/* ── Mobile quote pill — hot rose with glow ──────────────── */ +.mobile-quote-pill { + background: linear-gradient(180deg, #e11d48 0%, #be123c 100%) !important; + color: #fff !important; + box-shadow: 0 0 10px rgba(225, 29, 72, 0.25) !important; +} + +/* ── Progress bar — rose to teal gradient ────────────────── */ +.progress-fill { + background: linear-gradient(90deg, #e11d48 0%, #0d9488 100%) !important; +} + +/* ── Full-screen sidebar export-wrap ─────────────────────── */ +body.sidebar-focus-open .side-col .export-wrap { + background: transparent !important; + border-top: none !important; +} diff --git a/SVS-MSP-Calculator-base.css b/SVS-MSP-Calculator-base.css new file mode 100644 index 0000000..4e620cb --- /dev/null +++ b/SVS-MSP-Calculator-base.css @@ -0,0 +1,73 @@ +/* SVS MSP Calculator - Base */ +/* Extracted during Phase 5 to keep the HTML shell stable while splitting the monolithic stylesheet. */ + body { + background: var(--paper); + color: var(--ink); + font-family: 'Lato', sans-serif; + font-size: var(--text-body-size); + line-height: var(--text-body-line); + min-height: 100vh; + } + + /* ── TOP BAR ──────────────────────────────────────────────────── + Sticky header. z-index:100 sits below mobile panel (z:300) + and mobile pill (z:200). Background is --ink (cream) not --paper. + Contains: SVS logo SVG (inline) | quote ref + date (DM Mono). + ─────────────────────────────────────────────────────────────── */ + .top-bar { + position: sticky; + top: 0; + z-index: 100; + background: var(--top-bar-bg); + border-bottom: 2px solid var(--top-bar-border); + box-shadow: var(--top-bar-shadow); + padding: 14px 0; + display: flex; + justify-content: center; + } + .top-bar-inner { + width: 100%; + max-width: var(--page-max-width); + padding: 0 var(--page-gutter-x); + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + } + .top-bar-logo { margin-left: clamp(26px, 5.2vw, 78px); flex-shrink: 0; } + .top-bar-right { + font-family: 'DM Mono', monospace; + font-size: var(--text-meta-size); + letter-spacing: 0.07em; + color: var(--top-bar-meta); + text-align: right; + line-height: 1.55; + margin-left: auto; + } + + /* ── THEME TOGGLE BUTTON ──────────────────────────────────────── + Sits to the right of the quote ref/date in .top-bar-inner. + Slightly darker chip vs the cream top-bar bg so it reads as + a distinct control, not noise. Works on both theme top-bars. + ─────────────────────────────────────────────────────────────── */ + .theme-toggle-btn { + background: var(--theme-chip-bg); + border: 1px solid var(--theme-chip-border); + border-radius: 8px; + width: 36px; + height: 36px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + color: var(--theme-chip-fg); + transition: background var(--transition-fast); + flex-shrink: 0; + margin-left: 14px; + box-shadow: var(--theme-chip-shadow); + } + .theme-toggle-btn:hover { background: var(--theme-chip-hover); } + .theme-toggle-btn:active { background: var(--theme-chip-active); } + .theme-toggle-btn svg { display: block; } + + diff --git a/SVS-MSP-Calculator-components.css b/SVS-MSP-Calculator-components.css new file mode 100644 index 0000000..1d80d5d --- /dev/null +++ b/SVS-MSP-Calculator-components.css @@ -0,0 +1,2054 @@ +/* SVS MSP Calculator - Components */ +/* Extracted during Phase 5 to keep the HTML shell stable while splitting the monolithic stylesheet. */ + /* ── SECTION CARDS (I–VI) ─────────────────────────────────────── + Each section = position:relative card with: + .section-num — absolute, floats left outside card (Cinzel) + .section-header — flex row: title-block | summary badge | chevron + .section-body — collapsible content (overflow:hidden, JS toggle) + JS toggleSection(id) adds/removes .sec-open class on .section. + .sec-open .sec-chevron rotates 180deg (down→up arrow). + .sec-summary-badge is shown/hidden by setSummary() in update(). + ─────────────────────────────────────────────────────────────── */ + .section { + position: relative; + container-type: inline-size; + margin-left: var(--section-offset); + border-radius: var(--radius-card); + border: 1px solid var(--border); + background: var(--surface-section); + padding: var(--section-padding-top) var(--section-padding-x) var(--section-padding-bottom); + } + .fa-icon { + display: inline-block; + width: var(--icon-size, 1em); + height: var(--icon-size, 1em); + flex: 0 0 auto; + color: inherit; + background-color: currentColor; + vertical-align: middle; + mask-image: var(--fa-icon-url); + mask-repeat: no-repeat; + mask-position: center; + mask-size: contain; + -webkit-mask-image: var(--fa-icon-url); + -webkit-mask-repeat: no-repeat; + -webkit-mask-position: center; + -webkit-mask-size: contain; + } + .fa-icon--accent { color: var(--accent); } + .fa-icon--green { color: var(--green); } + .fa-icon--amber { color: var(--amber); } + .fa-icon--danger { color: var(--text-danger); } + .fa-icon--white { color: #fff; } + .fa-icon--theme { color: currentColor; } + /* ── FA Sharp Solid icons — inline data URIs for file:// compatibility ── */ + .fa-icon-file-invoice { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 384 512'%3E%3Cpath fill='currentColor' d='M240 0L0 0 0 512 384 512 384 144 240 0zm85.5 176L208 176 208 58.5 325.5 176zM64 416l0-128 256 0 0 128-256 0zM88 64l72 0 0 48-96 0 0-48 24 0zm0 96l72 0 0 48-96 0 0-48 24 0z'/%3E%3C/svg%3E"); } + .fa-icon-sun-bright { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath fill='currentColor' d='M312 544l-48 0 0-112 48 0 0 112zM180.5 397.4l-79.2 79.2-33.9-33.9 79.2-79.2 33.9 33.9zm328.1 45.3l-33.9 33.9-79.2-79.2 33.9-33.9 79.2 79.2zM288 384a128 128 0 1 1 0-256 128 128 0 1 1 0 256zM112 280l-112 0 0-48 112 0 0 48zm464 0l-112 0 0-48 112 0 0 48zM180.5 114.6l-33.9 33.9-79.2-79.2 33.9-33.9 79.2 79.2zM508.6 69.3l-79.2 79.2-33.9-33.9 79.2-79.2 33.9 33.9zM312 80l-48 0 0-112 48 0 0 112z'/%3E%3C/svg%3E"); } + .fa-icon-moon-stars { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M448-32l16 48 48 16-48 16-16 48-16-48-48-16 48-16 16-48zM314.7 83.1c-76.2 18.9-132.7 87.8-132.7 169.9 0 96.6 78.3 175 175 175 16.2 0 31.9-2.2 46.8-6.3-40.8 54.8-106.1 90.3-179.8 90.3-123.7 0-224-100.3-224-224S100.3 64 224 64c32.3 0 63 6.8 90.7 19.1zM384 352L355.2 268.8 272 240 355.2 211.2 384 128 412.8 211.2 496 240 412.8 268.8 384 352z'/%3E%3C/svg%3E"); } + .fa-icon-sparkles { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 512'%3E%3Cpath fill='currentColor' d='M480 32l32-72 32 72 72 32-72 32-32 72-32-72-72-32 72-32zM160 192l64-144 64 144 144 64-144 64-64 144-64-144-144-64 144-64zM480 344l32 72 72 32-72 32-32 72-32-72-72-32 72-32 32-72z'/%3E%3C/svg%3E"); } + .fa-icon-angles-up { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath fill='currentColor' d='M246.9 41.4l-22.6-22.6-22.6 22.6-160 160-22.6 22.6 45.3 45.3 22.6-22.6 137.4-137.4 137.4 137.4 22.6 22.6 45.3-45.3-22.6-22.6-160-160zm0 192l-22.6-22.6-22.6 22.6-160 160-22.6 22.6 45.3 45.3 22.6-22.6 137.4-137.4 137.4 137.4 22.6 22.6 45.3-45.3-182.6-182.6z'/%3E%3C/svg%3E"); } + .fa-icon-angles-down { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath fill='currentColor' d='M246.9 470.6l-22.6 22.6-22.6-22.6-160-160-22.6-22.6 45.3-45.3 22.6 22.6 137.4 137.4 137.4-137.4 22.6-22.6 45.3 45.3-182.6 182.6zm0-192l-22.6 22.6-22.6-22.6-160-160-22.6-22.6 45.3-45.3 22.6 22.6 137.4 137.4 160-160 45.3 45.3-22.6 22.6-160 160z'/%3E%3C/svg%3E"); } + .fa-icon-chevron-down { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M256.3 429.3l214.6-214.6 22.6-22.6-45.3-45.3-22.6 22.6-169.4 169.4-169.4-169.4-22.6-22.6-45.3 45.3 22.6 22.6 192 192 22.6 22.6z'/%3E%3C/svg%3E"); } + .fa-icon-chevron-left { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath fill='currentColor' d='M3 256l22.6 22.6 192 192 22.6 22.6 45.3-45.3-22.6-22.6-169.4-169.4 169.4-169.4 22.6-22.6-45.3-45.3-22.6 22.6-192 192-22.6 22.6z'/%3E%3C/svg%3E"); } + .fa-icon-chevron-right { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath fill='currentColor' d='M317.5 256L294.9 278.6 102.9 470.6 80.3 493.3 35 448 57.6 425.4 227 256 57.6 86.6 35 64 80.3 18.7 102.9 41.4 294.9 233.4 317.5 256z'/%3E%3C/svg%3E"); } + .fa-icon-square-check { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath fill='currentColor' d='M448 480l-448 0 0-448 448 0 0 448zM308.5 151l-119.4 164.2-69.1-69.1-33.9 33.9 88.9 88.9 19.8 19.9 16.5-22.7 135.9-186.9 14.1-19.4-38.8-28.3-14.1 19.4z'/%3E%3C/svg%3E"); } + .fa-icon-circle-check { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M256 512a256 256 0 1 1 0-512 256 256 0 1 1 0 512zm84.5-361l-119.4 164.2-69.1-69.1-33.9 33.9 88.9 88.9 19.8 19.9 16.5-22.7 135.9-186.9 14.1-19.4-38.8-28.3-14.1 19.4z'/%3E%3C/svg%3E"); } + .fa-icon-circle-info { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M256 512a256 256 0 1 0 0-512 256 256 0 1 0 0 512zM216 336l24 0 0-64-48 0 0-48 96 0 0 112 32 0 0 48-128 0 0-48 24 0zm72-144l-64 0 0-64 64 0 0 64z'/%3E%3C/svg%3E"); } + .fa-icon-square-info { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath fill='currentColor' d='M448 32l-448 0 0 448 448 0 0-448zM184 336l24 0 0-64-48 0 0-48 96 0 0 112 32 0 0 48-128 0 0-48 24 0zm72-208l0 64-64 0 0-64 64 0z'/%3E%3C/svg%3E"); } + .fa-icon-lightbulb-on { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 512'%3E%3Cpath fill='currentColor' d='M512 192c0 71.1-38.6 133.1-96 166.3l0 25.7-192 0 0-25.7C166.6 325.1 128 263.1 128 192 128 86 214 0 320 0S512 86 512 192zM224 528l0-96 192 0 0 96-192 0zm16-344c0-39.8 32.2-72 72-72l8 0 0-48-8 0c-66.3 0-120 53.7-120 120l0 8 48 0 0-8zM58.7 26.5l53.5 26.7-21.5 42.9C60.3 81 19.5 60.6 15.8 58.7L37.3 15.8 58.7 26.5zm544 42.9C579.6 81 561.8 89.9 549.3 96.2L527.8 53.3C558.2 38 599 17.7 602.7 15.8l21.5 42.9-21.5 10.7zM24 168l56 0 0 48-80 0 0-48 24 0zm560 0l56 0 0 48-80 0 0-48 24 0zM90.7 341.5C67.6 353 49.8 361.9 37.3 368.2L15.8 325.3C46.2 310 87 289.7 90.7 287.8l21.5 42.9-21.5 10.7zm458.5-53.7l74.9 37.5-21.5 42.9-74.9-37.5 21.5-42.9z'/%3E%3C/svg%3E"); } + .fa-icon-users { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 512'%3E%3Cpath fill='currentColor' d='M320 16a104 104 0 1 1 0 208 104 104 0 1 1 0-208zM96 88a72 72 0 1 1 0 144 72 72 0 1 1 0-144zm14.7 392l-110.7 0 48-192 107 0-41.8 181.2-2.5 10.8zm418.5 0l-2.5-10.8-41.8-181.2 107 0 48 192-110.7 0zM472 160a72 72 0 1 1 144 0 72 72 0 1 1 -144 0zM208 272l224 0 48 208-320 0 48-208z'/%3E%3C/svg%3E"); } + .fa-icon-user { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath fill='currentColor' d='M224 248a120 120 0 1 0 0-240 120 120 0 1 0 0 240zM432 512l-64-208-288 0-64 208 416 0z'/%3E%3C/svg%3E"); } + .fa-icon-desktop { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M512 32l-512 0 0 384 208 0-16 48-96 0 0 48 320 0 0-48-96 0-16-48 208 0 0-384zM448 96l0 224-384 0 0-224 384 0z'/%3E%3C/svg%3E"); } + .fa-icon-server { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath fill='currentColor' d='M448 32l-448 0 0 192 448 0 0-192zM280 104a24 24 0 1 1 0 48 24 24 0 1 1 0-48zm56 24a24 24 0 1 1 48 0 24 24 0 1 1 -48 0zM448 288l-448 0 0 192 448 0 0-192zM280 360a24 24 0 1 1 0 48 24 24 0 1 1 0-48zm56 24a24 24 0 1 1 48 0 24 24 0 1 1 0-64z'/%3E%3C/svg%3E"); } + .fa-icon-shield-check { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M267.6 4.5l207.5 80.5 19.2 7.4 1.2 20.5c2.9 50-4.9 126.3-37.3 200.9-32.7 75.2-91.1 150-189.4 192.6l-12.7 5.5-12.7-5.5C144.9 463.9 86.6 389.2 53.9 313.9 21.5 239.3 13.7 162.9 16.6 113L17.8 92.5 37 85 244.5 4.5 256 0 267.6 4.5zm45.8 165.3L227.8 287.6c-19.3-20-33.7-34.9-43.2-44.7l-34.5 33.3c6.2 6.4 27.2 28.1 63.1 65.2l19.8 20.6 16.8-23.1 102.4-140.8 14.1-19.4-38.8-28.2-14.1 19.4z'/%3E%3C/svg%3E"); } + .fa-icon-phone { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M0 64L128 0 224.8 128 144 208c33 70.4 89.6 127 160 160l80-80.8 128 96.8-64 128-16 0C193.4 512 0 318.6 0 80L0 64z'/%3E%3C/svg%3E"); } + .fa-icon-building { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 384 512'%3E%3Cpath fill='currentColor' d='M384 0L0 0 0 512 384 512 384 0zM240 352l0 112-96 0 0-112 96 0zM96 96l64 0 0 64-64 0 0-64zm192 0l0 64-64 0 0-64 64 0zM96 224l64 0 0 64-64 0 0-64zm192 0l0 64-64 0 0-64 64 0z'/%3E%3C/svg%3E"); } + .fa-icon-print { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M64 0l304 0 80 80 0 64-384 0 0-144zM0 192l512 0 0 192-64 0 0 128-384 0 0-128-64 0 0-192zM128 416l0 32 256 0 0-96-256 0 0 64zM456 272a24 24 0 1 0 -48 0 24 24 0 1 0 48 0z'/%3E%3C/svg%3E"); } + .fa-icon-file-code { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 384 512'%3E%3Cpath fill='currentColor' d='M0 0L240 0 384 144 384 512 0 512 0 0zM208 58.5L208 176 325.5 176 208 58.5zM154.2 295.6l15.6-18.2-36.4-31.2c-5 5.9-26.2 30.6-63.6 74.2L56.4 336c3.2 3.7 23.6 27.6 61.4 71.6l15.6 18.2 36.4-31.2c-7.2-8.5-24-28-50.2-58.6l34.6-40.4zm112-31.2l-15.6-18.2-36.4 31.2c7.2 8.5 24 28 50.2 58.6-26.2 30.6-43 50.1-50.2 58.6l36.4 31.2c5-5.8 26.2-30.6 63.6-74.2L327.6 336c-3.2-3.7-23.6-27.6-61.4-71.6z'/%3E%3C/svg%3E"); } + .fa-icon-location-dot { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 384 512'%3E%3Cpath fill='currentColor' d='M0 188.6C0 84.4 86 0 192 0S384 84.4 384 188.6C384 339.4 192 528 192 528S0 339.4 0 188.6zM192 256a64 64 0 1 0 0-128 64 64 0 1 0 0 128z'/%3E%3C/svg%3E"); } + .fa-icon-wrench-simple { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 384 512'%3E%3Cpath fill='currentColor' d='M128 160l64 64 64-64 0-160c74.6 26.4 128 92.4 128 176 0 71.1-38.6 133.1-96 166.3l0 169.7-192 0 0-169.7C38.6 309.1 0 247.1 0 176 0 92.4 53.4 26.4 128 0l0 160z'/%3E%3C/svg%3E"); } + .fa-icon-chart-line-up { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M64 32l0 384 448 0 0 64-512 0 0-448 64 0zM304 349.3c-6.6-6.6-38.6-38.6-96-96-30.7 30.7-52 52-64 64L98.7 272c8.2-8.2 37.1-37.1 86.6-86.6L208 162.7c6.6 6.6 38.6 38.6 96 96l65.4-65.4-65.4-65.4 176 0 0 176-65.4-65.4C345.1 308.2 308.2 345.1 304 349.3z'/%3E%3C/svg%3E"); } + .fa-icon-users-gear { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 512'%3E%3Cpath fill='currentColor' d='M320 224a104 104 0 1 0 0-208 104 104 0 1 0 0 208zM96 232a72 72 0 1 0 0-144 72 72 0 1 0 0 144zm14.7 248l2.5-10.8 41.8-181.2-107 0-48 192 110.7 0zm49.3 0l184.6 0-2.1-3.7-24-41.6 32.4-18.7-32.4-18.7c14.7-25.4 33.3-57.7 56-97l16.3-28.3-182.8 0-48 208zM616 160a72 72 0 1 0 -144 0 72 72 0 1 0 144 0zM544 288l-64 0 0 33.2c-12.7 4.3-24.2 11-34 19.7l-28.8-16.6-32 55.4 28.8 16.6c-1.3 6.4-1.9 12.9-1.9 19.7s.7 13.3 1.9 19.7l-28.8 16.6 32 55.4 28.8-16.6c9.8 8.7 21.4 15.4 34.1 19.7l0 33.2 64 0 0-33.2c12.7-4.3 24.2-11 34.1-19.7l28.8 16.6 32-55.4-28.8-16.6c1.3-6.4 1.9-12.9 1.9-19.7s-.7-13.3-1.9-19.7l28.8-16.6-32-55.4-28.8 16.6c-9.8-8.7-21.4-15.4-34-19.7l0-33.2zM472 416a40 40 0 1 1 80 0 40 40 0 1 1 -80 0z'/%3E%3C/svg%3E"); } + .fa-icon-network-wired { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath fill='currentColor' d='M328 88l0 48-80 0 0-48 80 0zM248 32l-56 0 0 160 64 0 0 32-256 0 0 64 128 0 0 32-64 0 0 160 192 0 0-160-64 0 0-32 192 0 0 32-64 0 0 160 192 0 0-160-64 0 0-32 128 0 0-64-256 0 0-32 64 0 0-160-136 0zM120 376l80 0 0 48-80 0 0-48zm336 0l0 48-80 0 0-48 80 0z'/%3E%3C/svg%3E"); } + .fa-icon-book-open-cover { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath fill='currentColor' d='M288 140l0 248.1 27.8-9.9c48.4-17.3 99.3-26.1 150.7-26.1l45.5 0 0-256-45.5 0c-36.7 0-73.1 6.3-107.6 18.6-37.5 13.4-61.2 21.8-70.9 25.3zM512 32l64 0 0 384-109.5 0c-44 0-87.7 7.6-129.2 22.4L288 456 238.6 438.4C197.2 423.6 153.5 416 109.5 416L0 416 0 32 109.5 32c44 0 87.7 7.6 129.2 22.4L288 72 337.4 54.4C378.8 39.6 422.5 32 466.5 32L512 32zM0 464l109.5 0c46.8 0 93.2 8 137.2 23.8l41.3 14.7 41.3-14.7c44-15.7 90.5-23.8 137.2-23.8l109.5 0 0 48-109.5 0c-41.3 0-82.2 7.1-121.1 21l-49.4 17.6-8.1 2.9-8.1-2.9-49.4-17.6c-38.9-13.9-79.8-21-121.1-21L0 512 0 464z'/%3E%3C/svg%3E"); } + .fa-icon-handshake { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath fill='currentColor' d='M288 64l0 0 128 0 48 32 112-64 0 288-70.4 56C411.3 282.5 346.8 218.5 312 184l0 0-47.4 47.4c-21.5 21.5-52.1 28.2-79.3 20.1-.4-.1-.8-.2-1.1-.3-7-2.2-13.8-5.4-20.1-9.5-.4-.3-.9-.6-1.3-.9-3.9-2.7-7.7-5.8-11.2-9.4L144 224 288 64zM160 64l63.4 0c-90.8 100.9-139.4 154.8-145.6 161.7 25.6 25.6 38.8 38.8 39.6 39.6 50 50 131 50 181 0l13.6-13.6 157.9 156.6-41.3 34.4c-26.9-26.9-44.5-44.5-52.7-52.7L342.1 424c8.7 8.7 25.2 25.2 49.6 49.6l-7.7 6.4-62.1 0c-31.3-31.3-50.6-50.6-57.9-57.9L230.1 456c13 13 21 21 24 24L192 480 0 320 0 32 112 96 160 64z'/%3E%3C/svg%3E"); } + .fa-icon-cloud { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath fill='currentColor' d='M448 480L0 480 0 336c0-62.7 40.1-116 96-135.8L96 176c0-79.5 64.5-144 144-144 55.4 0 103.5 31.3 127.6 77.1 14.2-8.3 30.8-13.1 48.4-13.1 53 0 96 43 96 96l0 49.1c38.3 22.1 64 63.5 64 110.9l0 128-128 0z'/%3E%3C/svg%3E"); } + .fa-icon-tv-retro { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M160-13.3c6.6 6.6 38.6 38.6 96 96 57.4-57.4 89.4-89.4 96-96L397.3 32c-12 12-33.3 33.3-64 64l178.7 0 0 384-512 0 0-384 178.7 0c-30.7-30.7-52-52-64-64L160-13.3zM384 160l-320 0 0 256 320 0 0-256zm88 72a24 24 0 1 0 -48 0 24 24 0 1 0 48 0zM448 336a24 24 0 1 0 0-48 24 24 0 1 0 0 48z'/%3E%3C/svg%3E"); } + .fa-icon-triangle-exclamation { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath fill='currentColor' d='M560 480L16 480 288-16 560 480zM260 356l0 56 56 0 0-56-56 0zm-4-196l12.8 160 38.4 0 12.8-160-64 0z'/%3E%3C/svg%3E"); } + .fa-icon-hard-drive { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath fill='currentColor' d='M448 32l-448 0 0 208 448 0 0-208zm0 256l-448 0 0 192 448 0 0-192zM224 384a32 32 0 1 1 64 0 32 32 0 1 1 -64 0zm128-32a32 32 0 1 1 0 64 32 32 0 1 1 0-64z'/%3E%3C/svg%3E"); } + .fa-icon-up-right-and-down-left-from-center { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='currentColor' d='M512 0l0 208-71-71-96 96-17 17c-8.8-8.8-25.1-25.1-49-49l-17-17 17-17 96-96-71-71 208 0zM0 512l0-208 71 71 96-96 17-17c8.8 8.8 25.1 25.1 49 49l17 17-17 17-96 96 71 71-208 0z'/%3E%3C/svg%3E"); } + .fa-icon-down-left-and-up-right-to-center { --fa-icon-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath fill='currentColor' d='M488.4-9.9c8.8 8.8 25.1 25.1 49 49l17 17-17 17-96 96 71 71-208 0 0-208 71 71 96-96 17-17zM272.4 272l0 208-71-71-96 96-17 17c-8.8-8.8-25.1-25.1-49-49l-17-17 17-17 96-96-71-71 208 0z'/%3E%3C/svg%3E"); } + .main-col > .section:first-of-type { margin-top: var(--space-lg); } + #sec-02 { order: 1; } + #sec-03 { order: 2; } + #sec-01 { order: 3; } + #sec-04 { order: 4; } + #sec-05 { order: 5; } + #sec-06 { order: 6; } + .section-header { + display: grid; + grid-template-columns: minmax(0, 1fr) auto auto; + align-items: start; + gap: var(--space-stack) var(--space-lg); + margin-bottom: var(--space-2xl); + } + .section:not(.sec-open) .section-header { + margin-bottom: 0; + grid-template-columns: minmax(0, 1fr) auto; + row-gap: var(--space-md); + column-gap: var(--space-stack); + } + .section-num { + font-family: 'Cinzel', serif; + font-weight: 700; + font-size: var(--section-num-size); + line-height: 1; + color: var(--border); + flex-shrink: 0; + width: var(--section-num-width); + user-select: none; + position: absolute; + left: calc(var(--section-offset) * -1); + top: calc(var(--section-padding-top) - 2px); + text-align: right; + } + .section-title-block { + min-width: 0; + max-width: none; + width: 100%; + grid-column: 1; + grid-row: 1; + } + .section:not(.sec-open) .section-title-block { + grid-column: 1; + grid-row: 1; + max-width: none; + width: 100%; + } + .section:not(.sec-open) .section-num { + position: absolute; + left: calc(var(--section-offset) * -1); + top: calc(var(--section-padding-top) - 2px); + width: var(--section-num-width); + font-size: clamp(22px, 2.2vw, 40px); + color: var(--accent); + text-align: right; + opacity: 0.82; + } + .section:not(.sec-open) .section-title { + max-width: none; + } + .section-title { + font-family: 'Poppins', sans-serif; + font-size: clamp(1.375rem, 1.5vw, 1.75rem); + font-weight: 600; + color: var(--ink); + line-height: var(--text-title-line); + word-break: break-word; + max-width: none; + text-wrap: pretty; + } + .section-title-tag { font-size: 0.9375rem; font-weight: 400; opacity: 0.6; } + .section-subtitle { + grid-column: 1 / -1; + grid-row: 3; + font-size: var(--text-copy-size); + color: var(--muted); + margin-top: var(--space-xs); + line-height: var(--text-copy-line); + max-width: none; + } + .section-badge { + font-family: 'DM Mono', monospace; + font-size: var(--text-label-size); + text-transform: uppercase; + letter-spacing: 0.1em; + padding: var(--control-pad-y-tight) var(--control-pad-x-tight); + border: 1px solid var(--border); + border-radius: var(--radius-control); + color: var(--muted); + display: inline-block; + margin-top: var(--space-stack-tight); + } + .section-toggle { cursor: pointer; user-select: none; } + .sec-chevron { + display: flex; + align-items: center; + justify-content: center; + align-self: start; + grid-column: 3; + grid-row: 1; + color: var(--muted); + transition: transform var(--transition-medium) ease, color var(--transition-fast); + flex-shrink: 0; + transform: rotate(0deg); + width: 34px; + height: 34px; + background: var(--surface-chevron); + border-radius: var(--radius-control); + margin-top: 2px; + } + .sec-open .sec-chevron { transform: rotate(180deg); color: var(--ink); background: var(--surface-chevron-active); } + .section-toggle:hover .sec-chevron { color: var(--ink); background: var(--surface-chevron-active); } + .sec-chevron svg { display: block; } + .section-body { + overflow: hidden; + opacity: 1; + transition: height 0.34s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.22s ease; + will-change: height, opacity; + } + .section-content { min-width: 0; } + .section-content > * + * { margin-top: var(--space-stack); } + .section-content > .collapsible-header + .collapsible-body, + .section-content > .collapsible-body + .collapsible-header { + margin-top: 0; + } + .section-content > .feature-card-grid + .collapsible-header, + .section-content > .callout-green + .feature-card-grid, + .section-content > .callout-red + .feature-card-grid { + margin-top: var(--space-stack-tight); + } + + @container (max-width: 520px) { + .section { + margin-left: 0; + padding: clamp(18px, 5cqi, 24px) clamp(18px, 5cqi, 22px) clamp(22px, 6cqi, 26px); + } + + .section-header, + .section:not(.sec-open) .section-header { + grid-template-columns: auto minmax(0, 1fr) auto; + column-gap: var(--space-stack-tight); + row-gap: var(--space-sm); + align-items: center; + } + + .section-num, + .section:not(.sec-open) .section-num { + position: static; + grid-column: 1; + grid-row: 1; + width: auto; + font-size: 1rem; + color: var(--accent); + text-align: left; + opacity: 0.85; + align-self: center; + margin-top: 0; + } + + .section-title-block, + .section:not(.sec-open) .section-title-block { + grid-column: 2; + grid-row: 1; + max-width: none; + width: 100%; + } + + .section-title { + font-size: 1.1rem; + max-width: none; + } + + .section-subtitle { + font-size: 0.8125rem; + max-width: none; + } + + .sec-chevron { + grid-column: 3; + grid-row: 1; + align-self: center; + margin-top: 0; + } + + } + + /* ── SECTION SUMMARY BADGE ────────────────────────────────────── + Shown only when section is COLLAPSED (display:none by default). + JS: setSummary(id, text) sets textContent + display:inline-block + when collapsed(secId) && !!text. Hidden when section is open. + On mobile (≤600px) placed in grid col 2 row 1 (top-right of header). + ─────────────────────────────────────────────────────────────── */ + @keyframes badgeFadeIn { + from { opacity: 0; transform: translateY(-4px); } + to { opacity: 1; transform: translateY(0); } + } + .sec-summary-badge { + display: none; + align-items: center; + font-family: 'DM Mono', monospace; + font-size: 13px; + font-weight: 500; + letter-spacing: 0.08em; + color: var(--accent); + background: var(--surface-summary-badge); + border: 2px solid var(--border-summary-badge); + border-radius: var(--radius-control); + padding: var(--control-pad-y-tight) var(--space-md); + white-space: normal; + line-height: var(--text-compact-line); + max-width: min(100%, 26ch); + margin-top: var(--space-md); + text-align: left; + align-self: flex-start; + animation: badgeFadeIn 0.25s ease both; + } + .sec-open .sec-summary-badge { + display: none !important; + } + .section:not(.sec-open) .sec-summary-badge { + width: fit-content; + max-width: 100%; + margin-top: var(--space-md); + } + .section:not(.sec-open) .sec-chevron { + position: static; + grid-column: 2; + grid-row: 1; + justify-self: end; + margin-top: 2px; + } + /* Override collapsed chevron + summary badge position at small container */ + @container (max-width: 520px) { + .section:not(.sec-open) .sec-chevron { + grid-column: 3; + align-self: center; + margin-top: 0; + } + .section:not(.sec-open) .sec-summary-badge { + width: 100%; + max-width: none; + margin-top: 0; + } + } + + /* Hide subtitle when collapsed — title + controls are enough */ + .section:not(.sec-open) .section-subtitle { display: none; } + + /* ── CONTROLS ROW (stepper + badge + summary — full-width row 2) ── */ + .sec-controls-row { + grid-column: 1 / -1; + grid-row: 2; + display: flex; + align-items: stretch; + gap: var(--space-stack-tight); + margin-top: var(--space-xs); + } + .sec-controls-row .num-stepper { + flex: 0 0 auto; + } + .sec-controls-row .num-input { + width: 56px; + } + .section .sec-controls-row > .section-badge, + .section .sec-controls-row > .sec-summary-badge { + display: flex; + align-items: center; + justify-content: center; + align-self: stretch; + min-height: 40px; + margin: 0; + padding: 0 var(--control-pad-x-tight); + white-space: nowrap; + line-height: 1; + border-width: 1px; + box-sizing: border-box; + max-width: none; + } + .section .sec-controls-row > .section-badge { + flex: 1 1 0%; + } + .section .sec-controls-row > .sec-summary-badge { + flex: 0 0 auto; + } + .sec-open .sec-controls-row > .sec-summary-badge { display: none !important; } + + /* ── Controls row: small container — stack full-width ── */ + @container (max-width: 520px) { + .sec-controls-row { + grid-row: 2; + flex-direction: column; + gap: 6px; + } + .sec-controls-row .num-stepper { + width: 100%; + max-width: none; + } + .sec-controls-row .num-input { + flex: 1 1 0%; + width: auto; + min-width: 0; + } + .sec-controls-row .step-btn { + width: 40px; + flex-shrink: 0; + } + .section .sec-controls-row > .section-badge, + .section .sec-controls-row > .sec-summary-badge { + width: 100%; + max-width: none; + align-self: stretch; + justify-content: center; + min-height: 36px; + } + } + + /* ── PILL TOGGLE (Section II — M365 vs BYOL) ─────────────────── + CSS-only toggle using hidden radio inputs + adjacent label styling. + input:checked + label gets accent background. + JS reads: document.getElementById("rateBYOL").checked + On mobile (≤600px) stacks vertically (grid-template-columns:1fr). + ─────────────────────────────────────────────────────────────── */ + .pill-toggle { + display: grid; + grid-template-columns: 1fr 1fr; + border: 1px solid var(--border); + border-radius: var(--radius-control); + overflow: hidden; + margin-bottom: 0; + } + .pill-toggle input[type=radio] { display: none; } + .pill-toggle label { + padding: var(--space-lg) var(--space-xl); + cursor: pointer; + border-right: 1px solid var(--border); + transition: background var(--transition-fast); + display: flex; + flex-direction: column; + gap: 6px; + } + .pill-toggle label:last-child { border-right: none; } + .pill-toggle input:focus-visible + label { + outline: 2px solid var(--accent); + outline-offset: -2px; + } + .pill-toggle input:checked + label { + background: var(--accent); + color: var(--text-on-accent); + } + .pill-toggle input:checked + label .pill-price { color: var(--text-on-accent); } + .pill-toggle input:checked + label .pill-desc { color: var(--text-on-accent-strong); } + .pill-toggle label .pill-price { + font-family: 'DM Mono', monospace; + font-size: 1.25rem; + font-weight: 500; + color: var(--ink); + } + .pill-toggle label .pill-price small { font-size: 0.875rem; opacity: 0.6; } + .pill-toggle label .pill-desc { font-size: 0.875rem; opacity: 0.7; } + .pill-toggle label .pill-savings { + display: block; + font-size: 0.75rem; + font-family: 'DM Mono', monospace; + color: var(--green); + margin-top: var(--space-xs); + letter-spacing: 0.02em; + } + .pill-toggle input:checked + label .pill-savings { color: var(--text-pill-savings-active); } + .pill-price .m365-price-grey { + color: var(--muted); + text-decoration: line-through; + opacity: 0.5; + margin-right: 6px; + font-size: 1rem; + } + .pill-toggle input:checked + label .m365-price-grey { + color: var(--text-on-accent); + opacity: 0.45; + } + + /* ── TIER SEGMENT (Section VI — VoIP Basic/Standard/Premium) ─── + 3-column radio toggle. JS activateTier(tier) adds .active class. + .active overrides text colours to white on accent background. + Rates: basic $28 | standard $35 | premium $45 /seat/mo. + ─────────────────────────────────────────────────────────────── */ + .tier-seg-wrap { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + border: 1px solid var(--border); + border-radius: var(--radius-control); + overflow: hidden; + margin-bottom: 0; + } + .tier-seg-wrap input[type=radio] { display: none; } + .tier-seg-wrap input[type=radio]:focus-visible + .tier-seg { + outline: 2px solid var(--accent); + outline-offset: -2px; + } + .tier-seg { + padding: var(--space-stack-roomy) var(--space-stack-tight); + cursor: pointer; + border-right: 1px solid var(--border); + text-align: center; + transition: background var(--transition-fast); + } + .tier-seg:last-of-type { border-right: none; } + .tier-seg.active { background: var(--accent); } + .tier-seg .tier-name { + font-family: 'DM Mono', monospace; + font-size: 0.875rem; + text-transform: uppercase; + letter-spacing: 0.07em; + color: var(--muted); + } + .tier-seg.active .tier-name { color: var(--text-on-accent); } + .tier-seg .tier-price { + font-family: 'DM Mono', monospace; + font-size: 1.375rem; + color: var(--ink); + margin-top: 3px; + } + .tier-seg.active .tier-price { color: var(--text-on-accent); } + .tier-seg .tier-sub { font-size: 0.75rem; color: var(--muted); margin-top: 2px; } + .tier-seg.active .tier-sub { color: var(--text-on-accent-strong); } + + /* ── INNER COLLAPSIBLES (What's Included / Add-Ons) ──────────── + Separate from section-level collapse. JS toggleCollapsible(id) + toggles .open on .collapsible-body and swaps +/- on toggle icon. + .addon-preview-pill pills shown when collapsed (JS toggleCollapsible). + ─────────────────────────────────────────────────────────────── */ + .collapsible-header { + display: flex; + align-items: center; + gap: var(--space-sm); + cursor: pointer; + padding: var(--space-md) 0; + border-top: 1px solid var(--border); + user-select: none; + } + .collapsible-header--mt16 { margin-top: var(--space-stack-roomy); } + .collapsible-header--addon { flex-wrap: wrap; gap: var(--space-xs); margin-top: 0; } + .collapsible-toggle { + color: var(--accent); + width: 22px; + flex-shrink: 0; + display: flex; + align-items: center; + transition: transform var(--transition-medium) ease; + } + .collapsible-toggle.open { transform: rotate(180deg); } + .collapsible-toggle .fa-icon { display: block; } + .collapsible-label { + font-family: 'DM Mono', monospace; + font-size: 13px; + text-transform: uppercase; + letter-spacing: 0.07em; + color: var(--muted); + } + .addon-preview-wrap { + display: flex; flex-wrap: wrap; gap: 5px; + width: 100%; padding-left: var(--space-3xl); margin-top: 6px; + } + .addon-preview-pill { + font-family: 'DM Mono', monospace; + font-size: 13px; + text-transform: uppercase; + letter-spacing: 0.07em; + color: var(--muted); + border: 1px solid var(--border); + border-radius: var(--radius-control); + padding: var(--control-pad-y-tight) var(--control-pad-x-tight); + white-space: nowrap; + transition: color var(--transition-fast), border-color var(--transition-fast), background var(--transition-fast); + } + .addon-preview-pill.active { + color: var(--green); + border-color: var(--green); + background: var(--surface-positive-pill); + } + .collapsible-body { + padding: var(--space-stack-tight) 0 var(--space-stack-tight) var(--space-3xl); + overflow: hidden; + max-height: 0; + opacity: 0; + transition: max-height 0.3s ease, opacity 0.2s ease; + } + .collapsible-body.open { + max-height: 2000px; + opacity: 1; + } + + /* FEATURE LIST */ + .feature-list { + list-style: none; + display: flex; + flex-direction: column; + gap: var(--space-md); + margin: var(--space-xs) 0 0; + padding: 0; + } + .feature-list li { + font-size: var(--text-copy-size); + color: var(--muted); + line-height: var(--text-copy-line); + padding-left: var(--space-lg); + position: relative; + } + .feature-list li::before { + content: '✓'; + position: absolute; + left: 0; + color: var(--green); + font-size: 11px; + } + .byol-mode .m365-feature { text-decoration: line-through; opacity: 0.55; } + .byol-mode .m365-feature::before { color: var(--amber); } + + /* ── NUMBER INPUTS ────────────────────────────────────────────── + .input-row — flex row: label left, .num-input right + .num-input — DM Mono, text-align:center, oninput→update() + On mobile (≤600px) input-row stacks (flex-direction:column) + and num-input goes full width. + ─────────────────────────────────────────────────────────────── */ + .input-row { + display: flex; + align-items: center; + justify-content: space-between; + padding: var(--space-stack-roomy) 0; + border-top: 1px solid var(--border); + } + .input-label { font-family: 'Lato', sans-serif; font-weight: 700; font-size: 16px; } + .input-sublabel { font-size: 13px; color: var(--muted); margin-top: 6px; line-height: var(--text-compact-line); } + .num-stepper { + display: flex; + align-items: stretch; + flex-shrink: 0; + } + .step-btn { + background: var(--surface-step); + border: 1px solid var(--surface-step-border); + color: var(--text-step); + font-size: 20px; + font-weight: 400; + width: 36px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: background 0.12s, color 0.12s; + flex-shrink: 0; + user-select: none; + line-height: 1; + } + .step-btn:first-child { border-radius: var(--radius-control) 0 0 var(--radius-control); border-right: none; } + .step-btn:last-child { border-radius: 0 var(--radius-control) var(--radius-control) 0; border-left: none; } + .step-btn:hover { background: var(--surface-step-hover); color: var(--ink); } + .step-btn:active { background: var(--surface-step-active); color: var(--btn-primary-fg); border-color: var(--accent); } + .num-input { + background: var(--surface-input); + border: 1px solid var(--surface-step-border); + border-radius: 0; + color: var(--ink); + font-family: 'DM Mono', monospace; + font-size: 22px; + width: 72px; + text-align: center; + padding: var(--space-sm); + outline: none; + } + .num-input:focus { border-color: var(--accent); } + .num-input::-webkit-inner-spin-button, + .num-input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; } + .num-input[type=number] { -moz-appearance: textfield; } + + /* ── ADDON ROWS ───────────────────────────────────────────────── + .addon-row — clickable label wrapping a hidden checkbox. + JS toggleAddon(cbId, rowId) toggles .selected class on row. + .selected gets accent-tinted background + border. + Price is right-aligned via margin-left:auto on .addon-price. + ─────────────────────────────────────────────────────────────── */ + .addon-grid { display: flex; flex-direction: column; gap: var(--space-sm); } + .addon-row { + display: flex; + align-items: flex-start; + gap: var(--space-md); + padding: var(--space-md) var(--space-stack); + border-radius: 8px; + cursor: pointer; + border: 1px solid transparent; + transition: background 0.12s, border-color 0.12s; + } + .addon-row:hover { + background: var(--surface-addon-hover); + border-color: var(--border-addon-hover); + } + .addon-row input[type=checkbox] { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + width: 18px; + height: 18px; + border: 2px solid var(--border); + border-radius: 4px; + background: transparent; + flex-shrink: 0; + margin-top: 3px; + cursor: pointer; + position: relative; + transition: background var(--transition-fast), border-color var(--transition-fast); + } + .addon-row input[type=checkbox]:checked { + background: var(--accent); + border-color: var(--accent); + } + .addon-row input[type=checkbox]:checked::after { + content: ''; + position: absolute; + left: 5px; + top: 1px; + width: 5px; + height: 10px; + border: solid #fff; + border-width: 0 2px 2px 0; + transform: rotate(45deg); + } + .addon-row:hover input[type=checkbox] { + border-color: var(--accent); + } + .addon-name { font-family: 'Lato', sans-serif; font-weight: 700; font-size: 15px; line-height: 1.35; } + .addon-price { + font-family: 'DM Mono', monospace; + font-size: 14px; + color: var(--accent); + white-space: nowrap; + margin-left: auto; + flex-shrink: 0; + } + .addon-desc { font-size: 13px; color: var(--muted); margin-top: 6px; line-height: var(--text-compact-line); } + + @container (max-width: 760px) { + .addon-row { + display: grid; + grid-template-columns: auto minmax(0, 1fr); + grid-template-rows: auto auto; + column-gap: var(--space-stack-tight); + row-gap: var(--space-sm); + padding: var(--space-stack) var(--space-md); + align-items: start; + } + + .addon-row input[type=checkbox] { + grid-column: 1; + grid-row: 2; + margin-top: 2px; + } + + .addon-row > div { + grid-column: 2; + grid-row: 2; + min-width: 0; + } + + .addon-price { + grid-column: 1 / -1; + grid-row: 1; + margin-left: 0; + font-size: 0.8125rem; + white-space: normal; + } + + .addon-name { + font-size: 0.875rem; + } + + .addon-desc { + font-size: 0.75rem; + } + } + + /* ── BYOL CALLOUTS (Section II) ──────────────────────────────── + Shown/hidden by JS based on BYOL toggle state. + #byolCalloutGreen — M365 savings message (shown when M365 selected) + #byolCalloutRed — missed savings warning (shown when BYOL selected) + display:flex + align-items:flex-start keeps icon pinned to + first line; text wrapped in so it never flows under icon. + ─────────────────────────────────────────────────────────────── */ + .callout-green { + background: var(--surface-success); + border: 1px solid var(--surface-success-border); + border-radius: var(--radius-control); + padding: var(--space-stack-roomy) var(--space-xl); + font-family: 'DM Mono', monospace; + font-size: 14px; + color: var(--green); + margin-bottom: 0; + line-height: 1.65; + display: flex; + align-items: flex-start; + gap: 9px; + } + .callout-red { + background: var(--surface-danger); + border: 1px solid var(--surface-danger-border); + border-radius: var(--radius-control); + padding: var(--space-stack-roomy) var(--space-xl); + font-family: 'DM Mono', monospace; + font-size: 14px; + color: var(--text-danger); + margin-bottom: 0; + line-height: 1.65; + display: flex; + align-items: flex-start; + gap: 9px; + } + .hidden { display: none !important; } + + /* ── ADMIN FEE PROGRESS BAR (Section I) ──────────────────────── + Shows progress toward $650 engagement threshold. + JS: progressEl width% = (baseSubtotal / ADMIN_FEE_MINIMUM) * 100 + baseSubtotal = users + endpoints + servers (NOT VoIP or ZT). + Turns green at 100% (threshold met), stays blue below. + ─────────────────────────────────────────────────────────────── */ + .progress-wrap { margin: var(--space-stack) 0 var(--space-stack-tight); } + /* Threshold bar promoted outside section-body for always-visible display */ + .sec-01-threshold.progress-wrap { margin: var(--space-stack-roomy) 0 0; } + .sec-01-threshold.floor-note { margin-top: var(--space-stack-tight); } + .section:not(.sec-open) .sec-01-threshold.progress-wrap { margin-top: var(--space-stack); margin-bottom: 0; } + .sec-open .sec-01-threshold + .floor-note + .section-body { margin-top: 0; } + .progress-label { + font-family: 'DM Mono', monospace; + font-size: 12px; + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--muted); + display: flex; + justify-content: space-between; + margin-bottom: 6px; + } + .progress-track { + height: 7px; + background: var(--border); + border-radius: 4px; + overflow: hidden; + } + .progress-fill { + height: 100%; + border-radius: 3px; + background: var(--accent); + transition: width 0.3s ease, background 0.3s; + } + + /* ── ADMIN FEE BREAKDOWN TABLE (Section I) ───────────────────── + Shows: Base Site Admin | ZT Supplement (if active) | Total. + .fee-total row has top border separator and bold text. + All values rendered by update() via getEl('sl-admin-val') etc. + ─────────────────────────────────────────────────────────────── */ + .fee-table { width: 100%; border-collapse: collapse; margin-top: var(--space-stack-roomy); font-size: 14px; } + .fee-table td { padding: var(--space-sm) 0; color: var(--muted); } + .fee-table td:last-child { text-align: right; font-family: 'DM Mono', monospace; color: var(--ink); } + .fee-table tr.fee-total td { border-top: 1px solid var(--border); padding-top: var(--space-stack); color: var(--ink); font-weight: 600; } + + /* ── FEATURE CARDS (Section I — What's Covered) ──────────────── + Static content — 8 cards in single-column grid. + Each card has icon (inline SVG) + title (Poppins) + desc (Lato). + Not dynamically rendered; content is hard-coded in HTML. + ─────────────────────────────────────────────────────────────── */ + .feature-card-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); + gap: var(--space-stack-roomy); + margin-top: 0; + } + .feature-card { + background: var(--surface-feature); + border: 1px solid var(--border); + border-radius: 10px; + padding: var(--space-stack) var(--space-stack-roomy); + } + .feature-card-title { font-family: 'Poppins', sans-serif; font-weight: 600; font-size: 0.9375rem; margin-bottom: var(--space-sm); display:flex; align-items:center; line-height: 1.35; } + .feature-card-desc { font-size: 0.8125rem; color: var(--muted); line-height: var(--text-copy-line); } + + .m365-app-strip { + border: 1px solid var(--border); + border-radius: 10px; + padding: var(--space-stack-roomy) var(--space-lg) var(--space-stack); + background: var(--surface-feature); + } + .m365-app-list { + display: grid; + grid-template-columns: repeat(6, minmax(0, 1fr)); + gap: var(--space-md); + } + .m365-app-item { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: var(--space-sm); + text-align: center; + padding: var(--space-stack-tight) var(--space-sm); + border-radius: var(--radius-control); + background: color-mix(in srgb, var(--surface-accent-soft) 44%, transparent); + } + .m365-app-icon { + width: 17px; + height: 17px; + object-fit: contain; + display: block; + } + .m365-app-name { + font-family: 'DM Mono', monospace; + font-size: 0.75rem; + letter-spacing: 0.05em; + color: var(--ink); + } + .m365-app-strip-note { + margin-top: var(--space-md); + font-family: 'DM Mono', monospace; + font-size: 0.75rem; + letter-spacing: 0.05em; + color: var(--muted); + } + .m365-app-note-byol { display: none; } + .m365-app-strip.byol-disabled .m365-app-item { + background: transparent; + border: 1px dashed var(--border); + } + .m365-app-strip.byol-disabled .m365-app-icon { + filter: grayscale(1) saturate(0.2); + opacity: 0.4; + } + .m365-app-strip.byol-disabled .m365-app-name { + color: var(--muted); + } + .m365-app-strip.byol-disabled .m365-app-note-default { display: none; } + .m365-app-strip.byol-disabled .m365-app-note-byol { + display: inline; + color: var(--amber); + } + + /* ── SIDEBAR (Desktop only, ≤1100px hidden) ───────────────────── + .sidebar-header — accent blue, shows "SVS MSP — LIVE QUOTE" + client name + .sidebar-body — all pricing lines, MRR total, notes, VS comparison, + nudge banner, export button + .sidebar-line — each service line (icon + label + value) + .sidebar-mrr — large Poppins 48px MRR total + IMPORTANT: nudgeBanner sits between .sidebar-header and .sidebar-body. + On mobile: the desktop sidebar is cloned into .mobile-panel-sheet + with _m IDs and synced by update() via syncEl/syncClass. + ─────────────────────────────────────────────────────────────── */ + .sidebar { + --sidebar-rule-color: color-mix(in srgb, var(--border) 88%, transparent); + --sidebar-copy-size: 0.84375rem; + --sidebar-copy-line: 1.5; + --sidebar-note-size: 0.78125rem; + --sidebar-mono-size: 0.75rem; + --sidebar-mrr-size: 2.8125rem; + background: var(--surface-sidebar); + border: 1px solid var(--border-sidebar); + border-radius: var(--radius-card); + overflow: hidden; + box-shadow: 0 18px 42px rgba(0,0,0,0.12); + } + .sidebar-focus-backdrop { + position: fixed; + inset: 0; + background: rgba(5, 11, 19, 0.58); + backdrop-filter: blur(4px); + -webkit-backdrop-filter: blur(4px); + opacity: 0; + pointer-events: none; + transition: opacity 0.2s ease; + z-index: 520; + } + .sidebar-header { + padding: var(--space-stack) 22px var(--space-md); + background: var(--surface-sidebar-header); + } + .sidebar-header-row { + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--space-md); + } + .sidebar-title { + font-family: 'DM Mono', monospace; + font-size: 0.6875rem; + letter-spacing: 0.18em; + text-transform: uppercase; + color: var(--text-sidebar-kicker); + margin-bottom: 0; + } + /* Print button inside sidebar header — only visible in focus mode */ + .sidebar-focus-print-btn { + display: none; + align-items: center; + justify-content: center; + height: 34px; + padding: 0 var(--space-stack); + border: 1px solid rgba(255,255,255,0.18); + border-radius: 10px; + background: rgba(255,255,255,0.06); + color: var(--text-sidebar-kicker); + font-family: 'DM Mono', monospace; + font-size: 0.6875rem; + letter-spacing: 0.08em; + text-transform: uppercase; + cursor: pointer; + transition: background var(--transition-fast) ease, border-color var(--transition-fast) ease; + flex: 0 0 auto; + margin-left: auto; + } + .sidebar-focus-print-btn:hover { + background: rgba(255,255,255,0.12); + border-color: rgba(255,255,255,0.28); + } + .sidebar-focus-print-btn:active { transform: translateY(1px); } + .sidebar-focus-toggle { + width: 34px; + height: 34px; + border: 1px solid rgba(255,255,255,0.18); + border-radius: 10px; + background: rgba(255,255,255,0.06); + color: var(--text-sidebar-kicker); + display: inline-flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: background var(--transition-fast) ease, border-color var(--transition-fast) ease, transform var(--transition-fast) ease; + flex: 0 0 auto; + } + .sidebar-focus-toggle:hover { + background: rgba(255,255,255,0.12); + border-color: rgba(255,255,255,0.28); + } + .sidebar-focus-toggle:active { transform: translateY(1px); } + .sidebar-focus-toggle:focus-visible { + outline: 2px solid rgba(255,255,255,0.5); + outline-offset: 2px; + } + .sidebar-focus-icon-close { display: none; } + .sidebar-focus-client { + display: none; + margin: var(--space-xs) 0 var(--space-lg); + padding-top: 0; + border-top: none; + } + .sidebar-focus-client-label { + display: block; + font-family: 'DM Mono', monospace; + font-size: 0.625rem; + letter-spacing: 0.14em; + text-transform: uppercase; + color: color-mix(in srgb, var(--ink) 62%, var(--muted)); + margin-bottom: var(--space-sm); + } + .sidebar-focus-client-name { + display: block; + font-family: 'Poppins', sans-serif; + font-size: 1rem; + font-weight: 600; + line-height: 1.25; + color: var(--ink); + margin-bottom: var(--space-stack); + } + .sidebar-body { padding: var(--space-stack) 22px var(--space-xl); background: var(--surface-sidebar-body); } + .sidebar-focus-columns { display: block; } + .sidebar-focus-col + .sidebar-focus-col { margin-top: var(--space-stack); } + .sidebar-focus-col > #vsComparison { margin-top: var(--space-lg); } + .sidebar-hero { + margin-bottom: var(--space-stack); + } + .sidebar-group { + display: flex; + flex-direction: column; + padding: var(--space-stack) var(--space-stack-roomy); + border-radius: var(--radius-control); + } + .sidebar-group--monthly { + background: var(--sidebar-zone-services, rgba(255, 255, 255, 0.03)); + } + .sidebar-group--tax { + background: transparent; + } + .sidebar-group--invoice { + background: var(--sidebar-zone-invoice, rgba(255, 255, 255, 0.05)); + } + .sidebar-group--value { + background: var(--sidebar-zone-value, rgba(255, 255, 255, 0.02)); + } + .sidebar-group + .sidebar-group { + margin-top: var(--space-stack); + } + .sidebar-group-title { + display: block; + flex: 0 0 auto; + min-height: 12px; + font-family: 'DM Mono', monospace; + font-size: 0.625rem; + letter-spacing: 0.16em; + text-transform: uppercase; + color: var(--muted); + margin: 0 0 var(--space-stack-tight); + } + .sidebar-line { + display: flex; + justify-content: space-between; + align-items: flex-start; + gap: var(--space-stack); + font-size: var(--sidebar-copy-size); + color: var(--muted); + line-height: var(--sidebar-copy-line); + padding: var(--space-stack-tight) 0; + border-bottom: 1px dashed var(--sidebar-rule-color); + } + .sidebar-line > span:first-child { flex: 1 1 auto; min-width: 0; } + .sidebar-line .val { + font-family: 'DM Mono', monospace; + color: var(--text-money); + font-size: var(--sidebar-copy-size); + line-height: 1.2; + letter-spacing: 0.02em; + flex: 0 0 auto; + padding-left: var(--space-sm); + text-align: right; + } + .sidebar-line .lbl-icon { margin-right: var(--space-sm); opacity: 0.82; } + .sidebar-mrr-label { + font-family: 'DM Mono', monospace; + font-size: 0.625rem; + letter-spacing: 0.16em; + text-transform: uppercase; + color: var(--muted); + margin-bottom: var(--space-sm); + } + .sidebar-mrr { + font-family: 'Poppins', sans-serif; + font-weight: 700; + font-size: var(--sidebar-mrr-size); + color: var(--text-money-hero); + line-height: 0.94; + letter-spacing: -0.03em; + margin-bottom: var(--space-stack-roomy); + } + .sidebar-line-value .val, + .sidebar-line-opportunity .val { + font-weight: 600; + } + .sidebar-line-value .lbl-icon .fa-icon, + .sidebar-line-opportunity .lbl-icon .fa-icon { + width: 15px; + height: 15px; + } + .sidebar-line-opportunity { + border-bottom-style: dotted; + } + .sidebar-line-opportunity .val { + color: var(--amber); + } + + /* ── VS IN-HOUSE COMPARISON ───────────────────────────────────── + Shown only when users > 0 OR endpoints > 0 (JS toggles .hidden). + Compares SVS MRR (annualised) vs 1-person Ottawa IT hire ($85K+tools) + and 5-person team ($420K+tools). Savings rows turn amber if SVS + costs MORE than the comparison (rare at low seat counts). + updateVsComparison(q) renders this section in update(). + ─────────────────────────────────────────────────────────────── */ + .vs-header { + display: flex; + flex-direction: column; + gap: var(--space-stack-tight); + margin-bottom: var(--space-stack-roomy); + } + .vs-brand-row { + display: flex; + align-items: center; + gap: var(--space-stack-tight); + } + .vs-brand-logo { + flex: 0 0 auto; + display: block; + } + .vs-brand-name { + font-family: 'Poppins', sans-serif; + font-size: 1rem; + font-weight: 600; + line-height: 1.2; + color: var(--ink); + letter-spacing: 0.02em; + } + .vs-table { width: 100%; border-collapse: collapse; font-size: 0.8125rem; line-height: 1.56; } + .vs-table td { padding: 9px var(--space-xs); vertical-align: middle; } + .vs-table td:last-child { text-align: right; font-family: 'DM Mono', monospace; white-space: nowrap; } + .vs-table tr:first-child td { padding-top: 2px; padding-bottom: var(--space-stack-roomy); border-bottom: 1px solid var(--border); } + .vs-table tr:nth-child(2) td, + .vs-table tr:nth-child(4) td { padding-top: var(--space-stack-roomy); } + .vs-save-row td { + padding: 11px var(--space-stack); + font-size: 0.71875rem; + font-family: 'DM Mono', monospace; + letter-spacing: 0.07em; + line-height: 1.35; + } + .vs-save-row td:first-child { border-radius: 8px 0 0 8px; } + .vs-save-row td:last-child { border-radius: 0 8px 8px 0; } + .vs-label { + font-family: 'DM Mono', monospace; + font-size: 0.6875rem; + letter-spacing: 0.16em; + text-transform: uppercase; + color: var(--muted); + margin-bottom: 0; + display: flex; + align-items: center; + gap: var(--space-sm); + } + .vs-label::after { content: ''; flex: 1; height: 1px; background: var(--border); } + + /* ── INSIGHT NUDGE BANNER ─────────────────────────────────────── + Contextual sales insight shown at bottom of sidebar. + Conditions (evaluated in update() → renderNudge()): + amber — ZT active + green — BYOL selected + users > 0 + green — PWM not selected + users > 0 + Auto-rotates every 30s via startNudgeRotation() (setInterval). + Manual nav via cycleNudge(dir) — does NOT reset the timer. + .nudge-nav-btn — SVG chevron pills (‹ ›), hidden when only 1 nudge. + BOTH #nudgeBanner and #nudgeBanner_m are updated by renderNudge() + via applyNudge('') and applyNudge('_m'). + nudgeBanner sits between .sidebar-header and .sidebar-body. + ─────────────────────────────────────────────────────────────── */ + .nudge-banner { + margin: 0; + padding: var(--space-xl) 22px; + font-size: 0.84375rem; + line-height: 1.6; + min-height: 132px; + box-sizing: border-box; + border-radius: var(--radius-control); + transition: opacity 0.18s ease, background var(--transition-medium) ease, border-color var(--transition-medium) ease; + } + .nudge-banner.nudge-fading { opacity: 0; } + .nudge-banner.amber { + background: var(--surface-warning); + color: var(--amber); + border-left: 4px solid var(--amber); + } + .nudge-banner.green { + background: var(--surface-success); + color: var(--green); + border-left: 4px solid var(--green); + } + .nudge-banner-label { + font-family: 'DM Mono', monospace; + font-size: 0.75rem; + text-transform: uppercase; + letter-spacing: 0.12em; + opacity: 1; + display: block; + margin-bottom: 0; + } + #nudgeCounter { + font-size: 0.75rem; + opacity: 0.55; + } + .nudge-nav-btn { + background: var(--surface-ghost); + border: 1px solid rgba(255,255,255,0.06); + cursor: pointer; + padding: 0; + width: 34px; + height: 34px; + border-radius: 7px; + display: flex; + align-items: center; + justify-content: center; + color: inherit; + flex-shrink: 0; + transition: background var(--transition-fast), transform 0.1s; + } + .nudge-nav-btn:hover { background: var(--surface-ghost-hover); transform: scale(1.06); } + .nudge-nav-btn:active { transform: scale(0.95); } + .nudge-nav-btn .fa-icon { display: block; --icon-size: 16px; } + + /* ── QUOTE SETTINGS BAR ───────────────────────────────────────── + Sits below the client bar, above Section I. + Left: contract term 3-way toggle. + Right: HST checkbox + one-time fee input. + Tokenized left alignment stays matched to the section gutter. + ─────────────────────────────────────────────────────────────── */ + + /* ── SECTIONS TOOLBAR (Collapse All / Expand All) ───────────────── */ + .sections-toolbar { + display: flex; + justify-content: flex-start; + margin-left: var(--section-offset); + margin-bottom: var(--space-stack); + } + .btn-toggle-all { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 6px; + min-height: var(--control-min-height); + font-family: 'DM Mono', monospace; + font-size: var(--text-meta-size); + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--muted); + background: none; + border: 1px solid var(--border); + border-radius: var(--radius-control); + padding: var(--control-pad-y) var(--control-pad-x); + cursor: pointer; + touch-action: manipulation; + transition: color var(--transition-fast), border-color var(--transition-fast), background var(--transition-fast); + } + .btn-toggle-all:hover { + color: var(--ink); + border-color: var(--accent); + background: var(--surface-accent-soft); + } + + .quote-settings-bar { + margin-left: var(--section-offset); + padding: clamp(18px, 2.4vw, 22px) clamp(20px, 2.8vw, 26px); + display: grid; + grid-template-columns: minmax(0, 1.55fr) 1px minmax(18rem, 0.95fr); + align-items: stretch; + gap: 0; + background: var(--surface-settings); + border: 1px solid var(--border); + border-radius: var(--radius-card); + overflow: hidden; + } + .qs-group { + display: flex; + flex-direction: column; + gap: var(--space-stack-tight); + container-type: inline-size; + min-width: 0; + width: 100%; + padding: 0 clamp(18px, 2.5cqi, 24px) 0 0; + max-width: none; + } + .qs-label { + font-family: 'DM Mono', monospace; + font-size: var(--text-meta-size); + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--muted); + } + .qs-label-row { + display: flex; + flex-direction: column; + gap: var(--space-sm); + margin-bottom: 2px; + } + .qs-term-wrap { + margin-bottom: 0; + border: 1px solid var(--border-term-wrap); + border-radius: var(--space-stack); + background: var(--surface-term-wrap); + box-shadow: var(--shadow-term-wrap); + } + .qs-term-wrap .tier-seg { + padding: clamp(14px, 2.5cqi, 16px) clamp(12px, 2.3cqi, 14px) clamp(14px, 2.4cqi, 15px); + background: var(--surface-term-tile); + transition: background 0.18s, border-color 0.18s, box-shadow 0.18s, transform 0.18s; + } + .qs-term-wrap .tier-seg:hover { + background: var(--surface-term-tile-hover); + } + .qs-term-wrap .tier-seg.active { + background: var(--surface-term-tile-active); + border-color: var(--border-term-tile-active); + box-shadow: var(--shadow-term-tile-active); + } + .qs-term-wrap .tier-name { + font-size: 12px; + font-weight: 400; + margin-bottom: 6px; + color: var(--text-term-name); + word-break: normal; + overflow-wrap: normal; + text-wrap: pretty; + } + .qs-term-wrap .tier-seg.active .tier-name { + color: var(--text-term-name-active); + font-weight: 700; + } + .qs-term-wrap .tier-sub { + margin-top: 0; + line-height: var(--text-compact-line); + overflow-wrap: break-word; + word-break: normal; + text-wrap: pretty; + color: var(--text-term-sub); + font-weight: 400; + } + .qs-term-wrap .tier-seg.active .tier-sub { + color: var(--text-term-sub-active); + font-weight: 400; + } + .qs-term-wrap .tier-price { display: none; } + + /* Best Value badge on 24-month */ + .qs-best-badge { + display: inline-flex; + max-width: 100%; + font-family: 'DM Mono', monospace; + font-size: 8px; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--text-best-value); + background: var(--surface-best-value); + border: 1px solid var(--border-best-value); + border-radius: var(--radius-control); + padding: 2px var(--space-sm); + vertical-align: middle; + margin-left: 5px; + line-height: 1.5; + white-space: nowrap; + } + .tier-seg.active .qs-best-badge { + color: var(--text-best-value-active); + background: var(--surface-best-value-active); + border-color: var(--border-best-value-active); + } + + /* Discount sub-text — !important overrides parent .tier-seg color inheritance */ + .qs-discount-sub { + color: var(--text-term-discount) !important; + font-weight: 700; + } + .tier-seg.active .qs-discount-sub { color: var(--text-term-discount-active) !important; } + .qs-savings-stack { + display: flex; + flex-direction: column; + gap: var(--space-stack-tight); + margin-top: var(--space-stack); + } + + /* Dynamic savings row — appears below selector when discounted term active */ + .qs-savings-row { + display: flex; + align-items: center; + gap: var(--space-stack-tight); + font-family: 'DM Mono', monospace; + font-size: 0.8125rem; + letter-spacing: 0.04em; + color: var(--green); + margin-top: 0; + padding: var(--space-stack) var(--space-lg); + border: 1px solid color-mix(in srgb, var(--green) 22%, var(--border)); + border-left: 4px solid var(--green); + border-radius: var(--radius-control); + background: color-mix(in srgb, var(--surface-positive-badge) 60%, transparent); + line-height: 1.5; + } + .qs-savings-row.hidden { display: none; } + .qs-savings-row .fa-icon { color: var(--green); flex-shrink: 0; opacity: 0.3; } + .qs-savings-row strong { color: var(--green); font-weight: 700; } + + /* Vertical divider between contract term and onboarding fee */ + .qs-divider { + width: 1px; + height: auto; + background: var(--surface-settings-divider); + margin: 0; + align-self: stretch; + } + + .qs-right { + display: flex; + flex-direction: column; + gap: var(--space-md); + padding: 0 0 0 clamp(18px, 2.5cqi, 24px); + justify-content: center; + min-width: 0; + max-width: none; + } + + @container (max-width: 1040px) { + .quote-settings-bar { + grid-template-columns: 1fr; + row-gap: var(--space-lg); + } + + .qs-group { + padding-right: 0; + } + + .qs-divider { + width: auto; + height: 1px; + } + + .qs-right { + padding-left: 0; + } + } + + /* ── Custom toggle switch (replaces native checkbox for Waive) ── */ + .qs-toggle-row { + display: flex; + align-items: center; + gap: 9px; + cursor: pointer; + user-select: none; + } + .qs-toggle-row input[type=checkbox] { display: none; } + .qs-toggle-row input[type=checkbox]:focus-visible + .qs-switch { + outline: 2px solid var(--accent); + outline-offset: 2px; + } + .qs-switch { + width: 34px; + height: 20px; + background: var(--surface-switch-off); + border-radius: 10px; + position: relative; + transition: background 0.2s; + flex-shrink: 0; + } + .qs-switch::after { + content: ''; + position: absolute; + width: 14px; + height: 14px; + background: var(--surface-switch-knob); + border-radius: 50%; + top: 3px; + left: 3px; + transition: left 0.2s, background 0.2s; + box-shadow: var(--shadow-switch-knob); + } + .qs-toggle-row input:checked ~ .qs-switch { background: var(--surface-switch-on); } + .qs-toggle-row input:checked ~ .qs-switch::after { left: 17px; } + .qs-fee-waive:has(input:disabled) { opacity: 0.5; cursor: default; } + .qs-fee-input:disabled { opacity: 0.4; cursor: not-allowed; } + + .qs-toggle-label { + font-family: 'DM Mono', monospace; + font-size: 12px; + color: var(--muted); + letter-spacing: 0.04em; + } + .qs-fee-row { + display: flex; + flex-direction: column; + gap: var(--space-stack-tight); + padding: var(--space-sm) 0 0; + } + .qs-fee-header { + display: flex; + align-items: center; + gap: var(--space-stack-tight); + } + .qs-fee-waive { + margin-left: 0; + align-self: flex-start; + padding: var(--control-pad-y-tight) var(--control-pad-x-tight); + border: 1px solid var(--border); + border-radius: 999px; + background: color-mix(in srgb, var(--surface-input) 85%, transparent); + } + .qs-fee-label { + font-family: 'DM Mono', monospace; + font-size: 13px; + color: var(--ink); + letter-spacing: 0.04em; + line-height: var(--text-compact-line); + } + .qs-fee-input-wrap { + display: flex; + align-items: center; + background: var(--surface-input); + border: 1px solid var(--border); + border-radius: 10px; + overflow: hidden; + width: 100%; + } + .qs-fee-dollar { + padding: 6px var(--space-sm); + font-family: 'DM Mono', monospace; + font-size: 14px; + color: var(--muted); + background: var(--surface-input); + border-right: 1px solid var(--border); + } + .qs-fee-input { + background: var(--surface-input); + border: none; + color: var(--ink); + font-family: 'DM Mono', monospace; + font-size: 18px; + width: 100%; + min-width: 0; + text-align: left; + padding: var(--space-md) var(--space-stack); + outline: none; + } + .qs-fee-input::placeholder { + color: color-mix(in srgb, var(--muted) 86%, transparent); + opacity: 1; + font-size: 15px; + } + .qs-fee-input::-webkit-inner-spin-button, + .qs-fee-input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; } + .qs-fee-input[type=number] { -moz-appearance: textfield; } + /* ── INLINE-STYLE REPLACEMENT CLASSES ─────────────────────────── + These replace presentational style="" attributes that previously + bypassed the design token system. All colours use tokens. + ─────────────────────────────────────────────────────────────── */ + + /* Section I — admin fee display row */ + /* .admin-fee-header base styles merged into the waived section definition at line ~1079 */ + .admin-fee-title { font-family: 'Poppins', sans-serif; font-weight: 600; font-size: 1.375rem; } + .admin-fee-val { font-family: 'DM Mono', monospace; font-size: 1.375rem; color: var(--accent); } + .admin-fee-sub { font-size: 0.75rem; color: var(--muted); margin-bottom: var(--space-stack); line-height: var(--text-compact-line); } + .floor-note { font-size: 12px; color: var(--muted); margin-top: var(--space-stack-tight); margin-bottom: var(--space-stack-roomy); font-family: 'DM Mono', monospace; letter-spacing: 0.08em; text-transform: uppercase; line-height: var(--text-compact-line); } + + /* Sidebar sub-line rows (users/endpoints/admin breakdown text) */ + .sl-sub { + font-size: var(--sidebar-mono-size); + color: var(--muted); + font-family: 'DM Mono', monospace; + line-height: 1.6; + letter-spacing: 0.02em; + padding: var(--space-xs) 0 var(--space-stack) var(--space-2xl); + } + .sl-sub-row { + display: grid; + align-items: start; + } + .sl-sub-row-base { + grid-template-columns: minmax(0, 1fr); + } + .sl-sub-row-addon { + grid-template-columns: minmax(0, 1fr) auto; + column-gap: var(--space-md); + padding: 5px 0 0; + border-top: 1px dotted color-mix(in srgb, var(--sidebar-rule-color) 88%, transparent); + } + .sl-sub-row + .sl-sub-row { + margin-top: 2px; + } + .sl-sub-copy { + min-width: 0; + } + .sl-sub-row-addon .sl-sub-copy { + padding-left: var(--space-md); + } + .sl-sub-val { + color: var(--muted); + text-align: right; + white-space: nowrap; + } + + /* Per-user cost section */ + .per-user-cost-sub { display: inline-block; font-size: 0.625rem; opacity: 0.6; font-weight: 400; margin-top: 3px; } + .sidebar-note-mono { font-size: var(--sidebar-mono-size); padding: 2px 0 6px; font-family: 'DM Mono', monospace; line-height: 1.45; } + + /* VS Comparison block */ + .vs-comparison-wrap { + margin-top: var(--space-stack-roomy); + margin-bottom: var(--space-stack); + padding: var(--space-xl) var(--space-xl) var(--space-lg); + background: var(--surface-compare); + border: 1px solid var(--border-compare); + border-radius: var(--radius-card); + } + .vs-svs-label { font-size: 0.9375rem; color: var(--text-vs-heading); font-weight: 600; line-height: 1.3; } + .vs-val-accent { color: var(--text-vs-accent); font-weight: 600; font-size: 0.9375rem; } + .vs-td-muted { color: var(--text-vs-muted); font-size: 0.8125rem; line-height: 1.45; } + .vs-td-icon { margin-right: 6px; opacity: 0.7; vertical-align: middle; } + .vs-footnote { + font-size: 0.6875rem; + color: var(--muted); + margin-top: var(--space-stack); + padding-top: var(--space-md); + border-top: 1px solid var(--border); + line-height: 1.6; + font-style: italic; + } + + /* Side note icons and savings highlight */ + .savings-amount { color: var(--green); } + .sl-otf-waived > span:first-child { color: var(--green); text-decoration: line-through; text-decoration-color: var(--green); } + .sl-otf-waived .val { color: var(--green); } + .sl-otf-waived .otf-amt { text-decoration: none; } + .sl-otf-waived .otf-amt-strike { text-decoration: line-through; text-decoration-color: var(--green); opacity: 0.7; margin-right: var(--space-xs); } + .sl-otf-waived .otf-waived-label { text-decoration: none; font-weight: 600; letter-spacing: 0.06em; font-size: 0.7rem; margin-right: var(--space-xs); } + + /* ── ADMIN FEE WAIVED display */ + .admin-fee-header { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-stack-tight); margin-bottom: 6px; } + .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: 0.75rem; font-weight: 700; letter-spacing: 0.08em; color: var(--green); background: var(--surface-positive-badge); border: 1px solid var(--border-positive-badge); border-radius: var(--radius-control); padding: 2px var(--space-sm); 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: var(--space-sm); font-family: 'DM Mono', monospace; font-size: 0.78125rem; letter-spacing: 0.04em; color: var(--green); background: var(--surface-positive-panel); border: 1px solid var(--border-positive-panel); border-radius: var(--radius-control); padding: var(--space-stack-tight) var(--space-stack); margin-top: var(--space-md); margin-bottom: 6px; } + .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: var(--space-stack-tight); } + .nudge-nav-group { display: flex; gap: var(--space-sm); } + + /* VoIP savings prompt */ + .savings-prompt { font-size: 0.8125rem; color: var(--muted); margin-top: var(--space-sm); } + + /* ── SIDEBAR UTILITY CLASSES ───────────────────────────────────── + .sl-muted — de-emphasised row labels/values + .sl-discount-val — green discount amount + .sl-hst-val — muted HST amount + ─────────────────────────────────────────────────────────────── */ + /* Sidebar utility classes — !important overrides .sidebar-line .val compound selector */ + .sl-muted { color: var(--muted) !important; font-size: 0.6875rem; } + .sl-discount-val { color: var(--green) !important; } + .sl-discount-detail { font-size: 0.7rem; opacity: 0.7; } + .sl-hst-val { color: var(--text-money) !important; font-size: var(--sidebar-copy-size); } + .sidebar-line-discount { border-bottom-style: dashed; opacity: 0.8; } + .sidebar-line.sidebar-line-hst { + margin-top: 0; + padding-top: var(--space-stack-tight); + padding-bottom: var(--space-stack-tight); + border-top: 1px dashed var(--sidebar-rule-color); + } + .sidebar-line.sidebar-line-total { + font-weight: 600; + margin-top: 2px; + } + .sl-hst-toggle { + justify-content: flex-start; + margin: var(--space-sm) 0; + } + + body.sidebar-focus-open { overflow: hidden; } + body.sidebar-focus-open .sidebar-focus-backdrop { + opacity: 1; + pointer-events: auto; + } + body.sidebar-focus-open .side-col { + position: relative; + z-index: 530; + } + body.sidebar-focus-open .sidebar-utility { display: none; } + body.sidebar-focus-open .side-col .export-wrap { display: none; } + body.sidebar-focus-open .sidebar-focus-print-btn { display: inline-flex; } + body.sidebar-focus-open .side-col .sidebar { + position: fixed; + top: calc(var(--top-bar-sticky-offset) + 10px); + left: 50%; + right: auto; + transform: translateX(-50%); + width: min(var(--page-max-width), calc(100vw - 20px)); + max-height: calc(100vh - var(--top-bar-sticky-offset) - 20px); + display: flex; + flex-direction: column; + z-index: 540; + box-shadow: 0 28px 64px rgba(0,0,0,0.28); + } + body.sidebar-focus-open .side-col .sidebar-focus-client { + display: block; + } + body.sidebar-focus-open .side-col .sidebar-body { + flex: 1 1 auto; + min-height: 0; + overflow-y: auto; + overscroll-behavior: contain; + padding: var(--space-4xl) var(--space-4xl) var(--space-3xl); + } + body.sidebar-focus-open .side-col .nudge-banner { + display: none !important; + } + body.sidebar-focus-open .side-col #vsComparison { + display: none !important; + } + body.sidebar-focus-open .side-col .sidebar-body > * { + min-width: 0; + } + body.sidebar-focus-open .side-col .sidebar-hero { + margin-bottom: var(--space-2xl); + } + body.sidebar-focus-open .side-col .sidebar-focus-columns { + display: grid; + grid-template-columns: minmax(0, 1.12fr) minmax(560px, 0.98fr); + gap: 0 42px; + align-items: start; + } + body.sidebar-focus-open .side-col .sidebar-focus-col { + display: flex; + flex-direction: column; + gap: var(--space-lg); + min-width: 0; + } + body.sidebar-focus-open .side-col .sidebar-focus-col + .sidebar-focus-col { + margin-top: 0; + } + body.sidebar-focus-open .side-col .sidebar-focus-col > .sidebar-group { + margin-top: 0; + } + body.sidebar-focus-open .side-col .sidebar-focus-col > #vsComparison { + margin-top: 0; + } + /* .export-wrap hidden in focus mode — see rule near line 1704 */ + body.sidebar-focus-open .sidebar-focus-icon-open { display: none; } + body.sidebar-focus-open .sidebar-focus-icon-close { display: inline-flex; } + .mobile-panel-sheet .sidebar-focus-toggle { display: none; } + .mobile-panel-sheet .sidebar-focus-print-btn { display: none; } + + /* ── VS COMPARISON CSS CLASSES (replace inline styles) ────────── + .vs-save-green — green "YOU SAVE" row background + .vs-save-amber — amber "Costs more" row background + .vs-val-green — green text for savings value/label + .vs-val-amber — amber text for "costs more" value/label + ─────────────────────────────────────────────────────────────── */ + .vs-save-green td { background: var(--surface-compare-success); } + .vs-save-amber td { background: var(--surface-compare-warning); } + /* VS value utility classes — !important overrides inherited td color */ + .vs-val-green { color: var(--green) !important; } + .vs-val-amber { color: var(--amber) !important; } + + /* ── SECTION CARD HOVER / OPEN POLISH ─────────────────────────── + Subtle left accent glow on hover; stronger treatment when open. + ─────────────────────────────────────────────────────────────── */ + .section { + transition: border-color 0.2s, box-shadow 0.2s; + } + .section:hover { + border-color: var(--section-hover-border); + box-shadow: var(--section-hover-shadow); + } + .section.sec-open { + border-color: var(--section-open-border); + box-shadow: var(--section-open-shadow); + } + + /* ── ADDON ROW SELECTED — stronger check indicator ────────────── + .selected gets a more prominent border + check indicator via + the checkbox's native accent-color. No pseudo-element needed. + ─────────────────────────────────────────────────────────────── */ + @keyframes addonPulse { + 0% { transform: scale(1); } + 50% { transform: scale(1.015); } + 100% { transform: scale(1); } + } + .addon-row.selected { + background: var(--surface-selected); + border-color: var(--accent); + box-shadow: inset 3px 0 0 0 var(--accent); + animation: addonPulse 0.2s ease; + } + .addon-row.selected .addon-name { color: var(--ink); } + .addon-row.selected .addon-price { color: var(--text-selected-accent); } + .addon-row.selected .addon-desc { color: color-mix(in srgb, var(--ink) 86%, var(--muted)); } + + /* ── QUOTE NOTES ──────────────────────────────────────────────── + Free-text notes field above export buttons. + Persisted in localStorage, included in print + JSON export. + ─────────────────────────────────────────────────────────────── */ + .quote-notes-wrap { + padding: var(--space-md) var(--space-xl) 0; + } + .quote-notes-label { + font-family: 'DM Mono', monospace; + font-size: 10px; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--muted); + display: block; + margin-bottom: 6px; + } + .quote-notes-input { + width: 100%; + background: var(--surface-card); + border: 1px solid var(--border); + border-radius: var(--radius-control); + color: var(--ink); + font-family: 'Poppins', sans-serif; + font-size: 12px; + padding: var(--space-sm) var(--space-stack-tight); + resize: vertical; + min-height: 56px; + max-height: 160px; + outline: none; + transition: border-color var(--transition-fast); + } + .quote-notes-input:focus { + border-color: var(--accent); + } + .quote-notes-input::placeholder { + color: var(--muted); + opacity: 0.5; + } + + /* ── EXPORT BUTTONS ───────────────────────────────────────────── + Primary CTA: Print / Save PDF + Secondary: Export JSON + Copy + ─────────────────────────────────────────────────────────────── */ + .export-wrap { + padding: var(--space-stack-roomy) var(--space-xl) var(--space-lg); + background: var(--surface-export); + border-top: 1px solid var(--border-export-top); + display: flex; + flex-direction: column; + gap: var(--space-stack-tight); + } + .btn-export { + width: 100%; + background: var(--accent); + color: var(--btn-primary-fg); + border: none; + border-radius: var(--radius-control); + min-height: var(--control-min-height); + padding: var(--control-pad-y) var(--control-pad-x); + font-family: 'DM Mono', monospace; + font-size: 0.75rem; + letter-spacing: 0.12em; + text-transform: uppercase; + cursor: pointer; + transition: background var(--transition-fast), transform 0.1s, filter var(--transition-fast), box-shadow var(--transition-fast); + display: flex; + align-items: center; + justify-content: center; + } + .btn-export:hover { + background: var(--btn-primary-hover); + filter: brightness(1.15); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25); + } + .btn-export:active { transform: scale(0.97); filter: brightness(0.95); } + .btn-export-secondary { + background: transparent; + border: 1px solid var(--border); + color: var(--muted); + font-size: 0.71875rem; + padding: var(--space-stack-tight) var(--space-stack); + } + .btn-export-secondary:hover { background: var(--card); border-color: var(--accent); color: var(--ink); } + + /* ── VOIP PHONE BILL SAVINGS ESTIMATOR (Section VI) ──────────── + Optional input: current monthly phone bill. + updateSavings(q) compares against voipTotal and shows green + savings message or amber warning if VoIP costs more. + On mobile stacks vertically (flex-direction:column). + ─────────────────────────────────────────────────────────────── */ + .savings-input-row { + display: flex; + align-items: center; + gap: var(--space-md); + margin-top: var(--space-stack-roomy); + padding-top: var(--space-stack-roomy); + border-top: 1px solid var(--border); + } + .savings-input-row label { + font-size: 0.875rem; + color: var(--muted); + flex: 1; + } + .savings-input-row input { + background: var(--card); + border: 1px solid var(--border); + border-radius: var(--radius-control); + color: var(--ink); + font-family: 'DM Mono', monospace; + font-size: 1.125rem; + width: 120px; + text-align: center; + padding: var(--control-pad-y-tight) var(--control-pad-x-tight); + outline: none; + } + .savings-result { + margin-top: var(--space-md); + background: var(--surface-success); + border: 1px solid var(--surface-success-border); + border-radius: var(--radius-control); + padding: var(--control-pad-y) var(--control-pad-x); + font-family: 'DM Mono', monospace; + font-size: 0.875rem; + color: var(--green); + line-height: 1.65; + } + /* Amber modifier — toggled by JS (classList.add/remove) when VoIP quote > current bill */ + .savings-result.savings-amber { + background: var(--surface-warning-panel); + border-color: var(--surface-warning-border); + color: var(--amber); + } + + /* ── BOTTOM PITCH BANNER ──────────────────────────────────────── + 4-column grid (2-col on tablet/mobile) outside the .outer grid. + .pitch-inner has margin-left:96px to align with section cards. + Columns: Security-First | Ottawa-Based | Flat-Rate | Scales With You + .pitch-footer — green strip at bottom with tagline. + Icons are inline SVG (FA Free 6.5.0 paths), accent blue. + ─────────────────────────────────────────────────────────────── */ + .pitch-wrap { + width: 100%; + padding: 0; + margin: 0; + } + .pitch-inner { + margin-left: 0; + background: var(--card); + border: none; + border-top: 1px solid var(--border); + border-radius: 0; + overflow: hidden; + } + .pitch-grid { + display: grid; + grid-template-columns: repeat(4, 1fr); + } + .pitch-item { + padding: 26px 22px; + border-right: 1px solid var(--border); + } + .pitch-item:last-child { border-right: none; } + .pitch-head { + display: flex; + align-items: center; + gap: var(--space-md); + margin-bottom: var(--space-stack-tight); + min-height: 28px; + } + .pitch-icon { + display: inline-flex; + align-items: center; + justify-content: center; + flex: 0 0 auto; + font-size: 20px; + color: var(--accent); + } + .pitch-title { + font-family: 'Poppins', sans-serif; + font-weight: 600; + font-size: 16px; + line-height: 1.3; + margin: 0; + } + .pitch-desc { font-size: var(--text-copy-size); color: var(--muted); line-height: var(--text-copy-line); } + .pitch-footer { + background: var(--surface-success); + border-top: 1px solid var(--surface-success-border); + padding: var(--space-md) var(--space-3xl); + font-family: 'DM Mono', monospace; + font-size: 13px; + color: var(--green); + letter-spacing: 0.05em; + text-align: center; + } + + @media (min-width: 1500px) { + .quote-settings-bar { + gap: var(--space-stack-tight); + } + + .section-header { + margin-bottom: var(--space-3xl); + } + + .sidebar-mrr { + font-size: 52px; + } + + .pill-toggle label { + padding: var(--space-xl) 22px; + } + } + + diff --git a/SVS-MSP-Calculator-glass.css b/SVS-MSP-Calculator-glass.css index 424c95b..b5a2004 100644 --- a/SVS-MSP-Calculator-glass.css +++ b/SVS-MSP-Calculator-glass.css @@ -18,23 +18,177 @@ html { --green: #63d8a2; --amber: #ffbe68; --glass-header-text: #5f6d7f; + --top-bar-bg: linear-gradient( + 180deg, + rgba(252, 255, 255, 0.96) 0%, + rgba(244, 249, 255, 0.93) 52%, + rgba(231, 240, 251, 0.91) 100% + ); + --top-bar-border: rgba(118, 143, 171, 0.35); + --top-bar-meta: var(--glass-header-text); + --theme-chip-bg: linear-gradient(180deg, rgba(247, 250, 255, 0.88), rgba(217, 229, 242, 0.82)); + --theme-chip-hover: linear-gradient(180deg, rgba(252, 254, 255, 0.94), rgba(226, 237, 248, 0.88)); + --theme-chip-active: linear-gradient(180deg, rgba(226, 236, 248, 0.95), rgba(205, 219, 235, 0.9)); + --theme-chip-fg: #223142; + --theme-chip-border: rgba(83, 117, 150, 0.24); + --theme-chip-shadow: 0 10px 24px rgba(6, 18, 31, 0.14); + --section-hover-border: rgba(105, 200, 255, 0.34); + --section-hover-shadow: + -4px 0 0 0 rgba(105, 200, 255, 0.36), + 0 20px 54px rgba(2, 8, 17, 0.38), + inset 0 1px 0 rgba(255, 255, 255, 0.07); + --section-open-border: rgba(105, 200, 255, 0.5); + --section-open-shadow: + -4px 0 0 0 rgba(105, 200, 255, 0.5), + 0 22px 58px rgba(2, 8, 17, 0.42), + inset 0 1px 0 rgba(255, 255, 255, 0.08); + --selection-bg: rgba(105, 200, 255, 0.28); + --selection-text: #f8fbff; + --top-bar-shadow: 0 8px 24px rgba(7, 18, 33, 0.1); + --glass-page-bg: + linear-gradient(142deg, #030b14 0%, #071420 20%, #0a1d2c 46%, #081721 72%, #040b13 100%), + linear-gradient(128deg, rgba(58, 182, 255, 0.2) 0%, rgba(58, 182, 255, 0) 30%), + linear-gradient(148deg, rgba(22, 205, 164, 0.15) 18%, rgba(22, 205, 164, 0) 48%), + radial-gradient(circle at 8% 10%, rgba(84, 200, 255, 0.3), transparent 26%), + radial-gradient(circle at 28% 34%, rgba(36, 204, 168, 0.22), transparent 22%), + radial-gradient(circle at 78% 18%, rgba(58, 166, 255, 0.2), transparent 24%), + radial-gradient(circle at 84% 72%, rgba(24, 188, 150, 0.16), transparent 20%), + linear-gradient(160deg, rgba(6, 14, 24, 0.74) 0%, rgba(4, 10, 19, 0.84) 100%); + --glass-page-overlay: + linear-gradient(132deg, rgba(70, 184, 255, 0.15) 0%, rgba(70, 184, 255, 0) 34%), + linear-gradient(148deg, rgba(28, 198, 158, 0.12) 18%, rgba(28, 198, 158, 0) 46%), + radial-gradient(circle at 16% 18%, rgba(72, 198, 255, 0.12), transparent 24%), + radial-gradient(circle at 82% 24%, rgba(24, 188, 150, 0.1), transparent 22%); + --glass-page-bg-mobile: + linear-gradient(150deg, #030b13 0%, #091521 28%, #0d1b29 58%, #07121b 100%), + linear-gradient(136deg, rgba(62, 186, 255, 0.16) 0%, rgba(62, 186, 255, 0) 36%), + linear-gradient(152deg, rgba(24, 198, 160, 0.11) 18%, rgba(24, 198, 160, 0) 46%), + radial-gradient(circle at 14% 12%, rgba(78, 196, 255, 0.24), transparent 24%), + radial-gradient(circle at 70% 22%, rgba(24, 184, 148, 0.16), transparent 20%), + radial-gradient(circle at 30% 48%, rgba(42, 162, 255, 0.15), transparent 22%); + --glass-page-overlay-mobile: + linear-gradient(138deg, rgba(66, 182, 255, 0.13) 0%, rgba(66, 182, 255, 0) 36%), + linear-gradient(154deg, rgba(26, 194, 156, 0.1) 18%, rgba(26, 194, 156, 0) 46%), + radial-gradient(circle at 78% 24%, rgba(26, 186, 150, 0.08), transparent 22%); + --glass-panel-bg: linear-gradient(180deg, rgba(16, 27, 43, 0.76), rgba(9, 17, 29, 0.68)); + --glass-section-bg: linear-gradient(180deg, rgba(17, 29, 46, 0.74), rgba(9, 17, 29, 0.66)); + --glass-panel-border: rgba(143, 183, 221, 0.18); + --glass-panel-shadow: + 0 18px 50px rgba(2, 8, 17, 0.32), + inset 0 1px 0 rgba(255, 255, 255, 0.06); + --glass-section-num: rgba(226, 239, 255, 0.18); + --glass-section-num-glow: 0 0 26px rgba(105, 200, 255, 0.1); + --glass-heading: #f4f9ff; + --glass-heading-soft: #f1f8ff; + --glass-client-border: rgba(143, 183, 221, 0.24); + --glass-client-placeholder: rgba(159, 179, 201, 0.72); + --glass-ghost-bg: rgba(255, 255, 255, 0.04); + --glass-ghost-border: rgba(143, 183, 221, 0.18); + --glass-ghost-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04); + --glass-ghost-hover-bg: rgba(105, 200, 255, 0.12); + --glass-ghost-hover-border: rgba(105, 200, 255, 0.3); + --glass-ghost-hover-text: #f2f8ff; + --glass-group-surface: rgba(5, 11, 21, 0.3); + --glass-input-surface: rgba(5, 11, 21, 0.34); + --surface-term-wrap: linear-gradient(180deg, rgba(12, 21, 34, 0.62), rgba(8, 15, 26, 0.54)); + --surface-term-tile: rgba(255, 255, 255, 0.02); + --surface-term-tile-hover: rgba(105, 200, 255, 0.08); + --surface-term-tile-active: + linear-gradient(180deg, rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0) 42%), + linear-gradient(135deg, rgba(62, 142, 190, 0.58) 0%, rgba(42, 107, 156, 0.62) 58%, rgba(24, 70, 118, 0.68) 100%); + --border-term-wrap: rgba(143, 183, 221, 0.18); + --border-term-tile-active: rgba(105, 200, 255, 0.16); + --shadow-term-wrap: inset 0 1px 0 rgba(255, 255, 255, 0.05); + --shadow-term-tile-active: + inset 0 1px 0 rgba(255, 255, 255, 0.08), + inset 0 -1px 0 rgba(3, 10, 20, 0.26); + --text-term-name: var(--muted); + --text-term-name-active: var(--text-on-accent); + --text-term-sub: var(--muted); + --text-term-sub-active: var(--text-on-accent); + --text-term-discount: #f2f8ff; + --text-term-discount-active: var(--text-on-accent); + --surface-best-value: rgba(99, 216, 162, 0.12); + --border-best-value: rgba(99, 216, 162, 0.26); + --text-best-value: #baf0d3; + --surface-best-value-active: rgba(255, 255, 255, 0.16); + --border-best-value-active: rgba(255, 255, 255, 0.34); + --text-best-value-active: #ffffff; + --text-pill-savings-active: #a8f0c8; + --glass-input-border: rgba(143, 183, 221, 0.2); + --glass-input-inset-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03); + --glass-input-focus-border: rgba(105, 200, 255, 0.55); + --glass-input-focus-shadow: 0 0 0 3px rgba(105, 200, 255, 0.16); + --glass-cta-gradient: linear-gradient(135deg, #76dbff 0%, #48b8ff 54%, #268ee3 100%); + --glass-cta-checked-bg: + linear-gradient(180deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0) 42%), + linear-gradient(135deg, rgba(94, 206, 255, 0.72) 0%, rgba(55, 156, 233, 0.78) 58%, rgba(28, 104, 190, 0.82) 100%); + --glass-cta-checked-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.12), + inset 0 -1px 0 rgba(3, 10, 20, 0.2); + --glass-sidebar-header-bg: + linear-gradient(180deg, rgba(255, 255, 255, 0.06) 0%, rgba(255, 255, 255, 0) 42%), + linear-gradient(135deg, rgba(63, 133, 175, 0.7) 0%, rgba(47, 113, 156, 0.68) 58%, rgba(31, 82, 126, 0.66) 100%); + --glass-sidebar-header-shadow: + inset 0 -1px 0 rgba(255, 255, 255, 0.08), + inset 0 1px 0 rgba(255, 255, 255, 0.12); + --glass-switch-track: rgba(255, 255, 255, 0.12); + --surface-switch-off: rgba(255, 255, 255, 0.15); + --surface-switch-on: var(--green); + --glass-switch-knob: rgba(250, 252, 255, 0.95); + --glass-switch-shadow: 0 2px 8px rgba(3, 9, 18, 0.28); + --glass-selected-bg: rgba(105, 200, 255, 0.12); + --glass-selected-border: rgba(105, 200, 255, 0.28); + --glass-selected-text: #f3fbff; + --surface-addon-hover: rgba(105, 200, 255, 0.08); + --border-addon-hover: rgba(105, 200, 255, 0.24); + --glass-feature-bg: linear-gradient(180deg, rgba(19, 31, 49, 0.8), rgba(10, 18, 30, 0.72)); + --glass-success-bg: linear-gradient(180deg, rgba(15, 48, 42, 0.82), rgba(10, 35, 30, 0.72)); + --glass-success-border: rgba(99, 216, 162, 0.26); + --glass-danger-bg: linear-gradient(180deg, rgba(62, 23, 34, 0.82), rgba(41, 14, 22, 0.74)); + --glass-danger-border: rgba(230, 117, 138, 0.26); + --glass-danger-text: #ffb7c6; + --glass-warning-bg: linear-gradient(180deg, rgba(66, 41, 12, 0.84), rgba(43, 27, 8, 0.76)); + --glass-warning-border: rgba(255, 190, 104, 0.26); + --glass-addon-active-bg: rgba(105, 200, 255, 0.16); + --glass-addon-active-border: rgba(105, 200, 255, 0.28); + --glass-addon-active-text: #dff3ff; + --glass-pill-inset-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); + --glass-divider: rgba(143, 183, 221, 0.14); + --glass-sidebar-placeholder: rgba(255, 255, 255, 0.76); + --glass-compare-bg: linear-gradient(180deg, rgba(14, 24, 39, 0.72), rgba(9, 16, 29, 0.62)); + --glass-compare-success: rgba(99, 216, 162, 0.14); + --glass-compare-warning: rgba(255, 190, 104, 0.14); + --glass-export-shadow: 0 14px 28px rgba(29, 108, 186, 0.26); + --glass-reset-text: #dceefe; + --glass-reset-hover-bg: rgba(105, 200, 255, 0.1); + --glass-reset-hover-border: rgba(105, 200, 255, 0.32); + --glass-reset-hover-text: #f2f8ff; + --sky: #7dd3fc; + --glass-modal-backdrop: rgba(2, 7, 15, 0.72); + --glass-modal-bg: linear-gradient(180deg, rgba(18, 29, 46, 0.86), rgba(10, 17, 29, 0.8)); + --glass-pitch-bg: linear-gradient(180deg, rgba(14, 25, 40, 0.72), rgba(9, 16, 28, 0.68)); + --glass-pitch-footer-bg: linear-gradient(135deg, rgba(11, 42, 34, 0.88), rgba(7, 28, 22, 0.86)); + --glass-pitch-footer-text: #8ee8bf; + --glass-mobile-sheet-bg: linear-gradient(180deg, rgba(12, 21, 34, 0.92), rgba(8, 14, 24, 0.9)); + --glass-mobile-row-bg: rgba(10, 18, 30, 0.84); + --glass-top-bar-mobile-bg: linear-gradient( + 180deg, + rgba(251, 255, 255, 0.95) 0%, + rgba(241, 247, 254, 0.91) 56%, + rgba(228, 238, 250, 0.89) 100% + ); + --glass-theme-toggle-mobile-shadow: 0 8px 20px rgba(6, 18, 31, 0.12); + --glass-mobile-panel-shadow: + 0 14px 36px rgba(2, 8, 17, 0.28), + inset 0 1px 0 rgba(255, 255, 255, 0.05); + --sidebar-zone-services: rgba(105, 200, 255, 0.03); + --sidebar-zone-invoice: rgba(105, 200, 255, 0.05); + --sidebar-zone-value: rgba(105, 200, 255, 0.02); } body { - background: - linear-gradient(138deg, #03070f 0%, #071120 14%, #10152a 30%, #1a1324 48%, #1a0d17 64%, #0a111b 82%, #050912 100%), - linear-gradient(125deg, rgba(44, 138, 255, 0.22) 0%, rgba(44, 138, 255, 0) 26%), - linear-gradient(142deg, rgba(18, 194, 152, 0.16) 18%, rgba(18, 194, 152, 0) 42%), - linear-gradient(154deg, rgba(118, 72, 224, 0.16) 34%, rgba(118, 72, 224, 0) 58%), - linear-gradient(164deg, rgba(198, 46, 86, 0.16) 52%, rgba(198, 46, 86, 0) 74%), - radial-gradient(circle at 8% 10%, rgba(72, 178, 255, 0.34), transparent 26%), - radial-gradient(circle at 26% 30%, rgba(32, 196, 144, 0.24), transparent 22%), - radial-gradient(circle at 58% 18%, rgba(116, 82, 222, 0.24), transparent 22%), - radial-gradient(circle at 88% 16%, rgba(200, 60, 92, 0.24), transparent 20%), - radial-gradient(circle at 76% 56%, rgba(42, 126, 255, 0.2), transparent 22%), - radial-gradient(circle at 24% 78%, rgba(112, 44, 138, 0.22), transparent 22%), - radial-gradient(circle at 92% 86%, rgba(18, 168, 132, 0.2), transparent 20%), - linear-gradient(160deg, rgba(7, 14, 25, 0.72) 0%, rgba(5, 10, 19, 0.8) 100%); + background: var(--glass-page-bg); background-attachment: fixed; color: var(--ink); position: relative; @@ -45,11 +199,7 @@ body::before { position: fixed; inset: 0; pointer-events: none; - background: - linear-gradient(132deg, rgba(58, 154, 255, 0.16) 0%, rgba(58, 154, 255, 0) 34%), - linear-gradient(145deg, rgba(28, 201, 154, 0.12) 18%, rgba(28, 201, 154, 0) 44%), - linear-gradient(156deg, rgba(122, 84, 232, 0.12) 38%, rgba(122, 84, 232, 0) 60%), - linear-gradient(168deg, rgba(214, 68, 104, 0.12) 58%, rgba(214, 68, 104, 0) 78%); + background: var(--glass-page-overlay); opacity: 0.9; z-index: 0; } @@ -61,30 +211,17 @@ body::before { } ::selection { - background: rgba(105, 200, 255, 0.28); - color: #f8fbff; + background: var(--selection-bg); + color: var(--selection-text); } .top-bar { - position: sticky !important; - top: 0 !important; - z-index: 100 !important; - background: linear-gradient( - 180deg, - rgba(252, 255, 255, 0.96) 0%, - rgba(244, 249, 255, 0.93) 52%, - rgba(231, 240, 251, 0.91) 100% - ) !important; - border-bottom: 1px solid rgba(118, 143, 171, 0.35) !important; - box-shadow: 0 8px 24px rgba(7, 18, 33, 0.1) !important; + border-bottom-width: 1px !important; + box-shadow: var(--top-bar-shadow) !important; backdrop-filter: blur(18px) saturate(135%); -webkit-backdrop-filter: blur(18px) saturate(135%); } -.top-bar-right { - color: var(--glass-header-text) !important; -} - @media (min-width: 1101px) { .outer { padding-top: var(--sidebar-top-gap) !important; @@ -95,66 +232,32 @@ body::before { } } -.theme-toggle-btn { - background: linear-gradient(180deg, rgba(247, 250, 255, 0.88), rgba(217, 229, 242, 0.82)) !important; - border: 1px solid rgba(83, 117, 150, 0.24) !important; - color: #223142 !important; - box-shadow: 0 10px 24px rgba(6, 18, 31, 0.14) !important; -} - -.theme-toggle-btn:hover { - background: linear-gradient(180deg, rgba(252, 254, 255, 0.94), rgba(226, 237, 248, 0.88)) !important; -} - -.theme-toggle-btn:active { - background: linear-gradient(180deg, rgba(226, 236, 248, 0.95), rgba(205, 219, 235, 0.9)) !important; -} - .section, .quote-settings-bar, .sidebar, -.sidebar-utility .btn-reset-quote, +.sidebar-utility .btn-export, +.sidebar-utility .btn-export-secondary, .mobile-panel-sheet, .mobile-panel-close-row, .mobile-panel-actions, .confirm-modal-card, -.feature-card, -.addon-row, .vs-comparison-wrap, .export-wrap, .pitch-inner { - background: linear-gradient(180deg, rgba(16, 27, 43, 0.76), rgba(9, 17, 29, 0.68)) !important; - border-color: rgba(143, 183, 221, 0.18) !important; - box-shadow: - 0 18px 50px rgba(2, 8, 17, 0.32), - inset 0 1px 0 rgba(255, 255, 255, 0.06) !important; + background: var(--glass-panel-bg) !important; + border-color: var(--glass-panel-border) !important; + box-shadow: var(--glass-panel-shadow) !important; backdrop-filter: blur(18px) saturate(135%); -webkit-backdrop-filter: blur(18px) saturate(135%); } .section { - background: linear-gradient(180deg, rgba(17, 29, 46, 0.74), rgba(9, 17, 29, 0.66)) !important; -} - -.section:hover { - border-color: rgba(105, 200, 255, 0.34) !important; - box-shadow: - -4px 0 0 0 rgba(105, 200, 255, 0.36), - 0 20px 54px rgba(2, 8, 17, 0.38), - inset 0 1px 0 rgba(255, 255, 255, 0.07) !important; -} - -.sec-open { - border-color: rgba(105, 200, 255, 0.5) !important; - box-shadow: - -4px 0 0 0 rgba(105, 200, 255, 0.5), - 0 22px 58px rgba(2, 8, 17, 0.42), - inset 0 1px 0 rgba(255, 255, 255, 0.08) !important; + background: var(--glass-section-bg) !important; } .section-num { - color: rgba(226, 239, 255, 0.18) !important; - text-shadow: 0 0 26px rgba(105, 200, 255, 0.1); + color: var(--glass-section-num) !important; + text-shadow: var(--glass-section-num-glow); } .section-title, @@ -162,7 +265,7 @@ body::before { .sidebar-mrr, .sidebar-line .val, .vs-svs-label { - color: #f4f9ff !important; + color: var(--glass-heading) !important; } .section-subtitle, @@ -184,12 +287,12 @@ body::before { } .client-input { - color: #f4f9ff !important; - border-bottom-color: rgba(143, 183, 221, 0.24) !important; + color: var(--glass-heading) !important; + border-bottom-color: var(--glass-client-border) !important; } .client-input::placeholder { - color: rgba(159, 179, 201, 0.72) !important; + color: var(--glass-client-placeholder) !important; } .sec-chevron, @@ -199,10 +302,10 @@ body::before { .btn-export-secondary, .mobile-panel-close, .nudge-nav-btn { - background: rgba(255, 255, 255, 0.04) !important; - border-color: rgba(143, 183, 221, 0.18) !important; + background: var(--glass-ghost-bg) !important; + border-color: var(--glass-ghost-border) !important; color: var(--muted) !important; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04); + box-shadow: var(--glass-ghost-shadow); } .sec-open .sec-chevron, @@ -212,16 +315,16 @@ body::before { .btn-export-secondary:hover, .nudge-nav-btn:hover, .mobile-panel-close:hover { - background: rgba(105, 200, 255, 0.12) !important; - border-color: rgba(105, 200, 255, 0.3) !important; - color: #f2f8ff !important; + background: var(--glass-ghost-hover-bg) !important; + border-color: var(--glass-ghost-hover-border) !important; + color: var(--glass-ghost-hover-text) !important; } .pill-toggle, .tier-seg-wrap, .qs-fee-input-wrap { - background: rgba(5, 11, 21, 0.3) !important; - border-color: rgba(143, 183, 221, 0.18) !important; + background: var(--glass-group-surface) !important; + border-color: var(--glass-ghost-border) !important; } .pill-toggle label, @@ -232,7 +335,7 @@ body::before { .pill-toggle label:hover, .tier-seg:hover, .addon-row:hover { - background: rgba(255, 255, 255, 0.04) !important; + background: var(--glass-ghost-bg) !important; } .tier-seg.active, @@ -240,28 +343,20 @@ body::before { .confirm-btn-danger, .mobile-quote-pill, .progress-fill { - background: linear-gradient(135deg, #7ad6ff 0%, #4da8ff 52%, #337dff 100%) !important; - color: #ffffff !important; + background: var(--glass-cta-gradient) !important; + color: var(--text-on-accent) !important; } .pill-toggle input:checked + label { - background: - linear-gradient(180deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0) 42%), - linear-gradient(135deg, rgba(103, 182, 248, 0.7) 0%, rgba(63, 122, 210, 0.76) 58%, rgba(45, 82, 155, 0.82) 100%) !important; - color: #ffffff !important; - box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.12), - inset 0 -1px 0 rgba(3, 10, 20, 0.2) !important; + background: var(--glass-cta-checked-bg) !important; + color: var(--text-on-accent) !important; + box-shadow: var(--glass-cta-checked-shadow) !important; } .sidebar-header { - background: - linear-gradient(180deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0) 44%), - linear-gradient(135deg, rgba(105, 188, 250, 0.82) 0%, rgba(71, 132, 224, 0.8) 54%, rgba(67, 72, 156, 0.76) 100%) !important; - color: #ffffff !important; - box-shadow: - inset 0 -1px 0 rgba(255, 255, 255, 0.08), - inset 0 1px 0 rgba(255, 255, 255, 0.12) !important; + background: var(--glass-sidebar-header-bg) !important; + color: var(--text-on-accent) !important; + box-shadow: var(--glass-sidebar-header-shadow) !important; } .pill-toggle input:checked + label .pill-desc, @@ -269,7 +364,7 @@ body::before { .tier-seg.active .tier-name, .tier-seg.active .tier-price, .tier-seg.active .tier-sub { - color: #ffffff !important; + color: var(--text-on-accent-strong) !important; } .num-input, @@ -277,77 +372,89 @@ body::before { .qs-fee-dollar, .qs-fee-input-wrap, .mobile-panel-sheet .sidebar-body { - background: rgba(5, 11, 21, 0.34) !important; + background: var(--glass-input-surface) !important; } .num-input, .qs-fee-input { - border-color: rgba(143, 183, 221, 0.2) !important; - color: #f2f8ff !important; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03); + border-color: var(--glass-input-border) !important; + color: var(--glass-ghost-hover-text) !important; + box-shadow: var(--glass-input-inset-shadow); } .num-input:focus, .qs-fee-input:focus, .client-input:focus-visible { - border-color: rgba(105, 200, 255, 0.55) !important; - box-shadow: 0 0 0 3px rgba(105, 200, 255, 0.16) !important; + border-color: var(--glass-input-focus-border) !important; + box-shadow: var(--glass-input-focus-shadow) !important; } .qs-switch { - background: rgba(255, 255, 255, 0.12) !important; + background: var(--surface-switch-off) !important; } +.qs-toggle-row input:checked ~ .qs-switch { + background: var(--surface-switch-on) !important; +} .qs-switch::after { - background: rgba(250, 252, 255, 0.95) !important; - box-shadow: 0 2px 8px rgba(3, 9, 18, 0.28); + background: var(--glass-switch-knob) !important; + box-shadow: var(--glass-switch-shadow); } .addon-row.selected { - background: rgba(105, 200, 255, 0.12) !important; - border-color: rgba(105, 200, 255, 0.28) !important; + background: var(--glass-selected-bg) !important; + border-color: var(--glass-selected-border) !important; } .addon-row.selected .addon-name, -.addon-row.selected .addon-price { - color: #9edcff !important; +.addon-row.selected .addon-price, +.addon-row.selected .addon-desc { + color: var(--glass-selected-text) !important; } .feature-card { - background: linear-gradient(180deg, rgba(19, 31, 49, 0.8), rgba(10, 18, 30, 0.72)) !important; + background: var(--glass-feature-bg) !important; + border-color: var(--glass-panel-border) !important; + box-shadow: none !important; +} + +.addon-row { + background: transparent !important; + border-color: transparent !important; + box-shadow: none !important; } .callout-green, .nudge-banner.green, .admin-waive-savings { - background: linear-gradient(180deg, rgba(15, 48, 42, 0.82), rgba(10, 35, 30, 0.72)) !important; - border-color: rgba(99, 216, 162, 0.26) !important; + background: var(--glass-success-bg) !important; + border-color: var(--glass-success-border) !important; color: var(--green) !important; } .callout-red { - background: linear-gradient(180deg, rgba(62, 23, 34, 0.82), rgba(41, 14, 22, 0.74)) !important; - border-color: rgba(230, 117, 138, 0.26) !important; - color: #ffb7c6 !important; + background: var(--glass-danger-bg) !important; + border-color: var(--glass-danger-border) !important; + color: var(--glass-danger-text) !important; } .nudge-banner.amber, .admin-fee-waived-badge { - background: linear-gradient(180deg, rgba(66, 41, 12, 0.84), rgba(43, 27, 8, 0.76)) !important; - border-color: rgba(255, 190, 104, 0.26) !important; + background: var(--glass-warning-bg) !important; + border-color: var(--glass-warning-border) !important; color: var(--amber) !important; } .admin-waive-savings, .admin-fee-waived-badge, .addon-preview-pill.active { - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); + box-shadow: var(--glass-pill-inset-shadow); } .addon-preview-pill.active { - background: rgba(105, 200, 255, 0.16) !important; - border-color: rgba(105, 200, 255, 0.28) !important; - color: #dff3ff !important; + background: var(--glass-addon-active-bg) !important; + border-color: var(--glass-addon-active-border) !important; + color: var(--glass-addon-active-text) !important; } .collapsible-header, @@ -359,12 +466,12 @@ body::before { .export-wrap, .mobile-panel-close-row, .mobile-panel-actions { - border-color: rgba(143, 183, 221, 0.14) !important; + border-color: var(--glass-divider) !important; } .sidebar-title, .sidebar-client.placeholder { - color: rgba(255, 255, 255, 0.76) !important; + color: var(--glass-sidebar-placeholder) !important; } .sidebar-body, @@ -386,108 +493,119 @@ body::before { } .vs-comparison-wrap { - background: linear-gradient(180deg, rgba(14, 24, 39, 0.72), rgba(9, 16, 29, 0.62)) !important; + background: var(--glass-compare-bg) !important; } .vs-save-green td { - background: rgba(99, 216, 162, 0.14) !important; + background: var(--glass-compare-success) !important; } .vs-save-amber td { - background: rgba(255, 190, 104, 0.14) !important; + background: var(--glass-compare-warning) !important; } .export-wrap { - border-top: 1px solid rgba(143, 183, 221, 0.14) !important; + border-top: 1px solid var(--glass-divider) !important; +} +body.sidebar-focus-open .side-col .export-wrap { + background: transparent !important; + border-color: transparent !important; + border-top: none !important; + box-shadow: none !important; + backdrop-filter: none; } .btn-export { - box-shadow: 0 14px 28px rgba(29, 108, 186, 0.26) !important; + box-shadow: var(--glass-export-shadow) !important; } .btn-export:hover, .mobile-quote-pill:hover { - filter: brightness(1.05); + filter: brightness(1.2) !important; + box-shadow: 0 4px 16px rgba(99, 127, 136, 0.35) !important; +} +.btn-export:active { + filter: brightness(0.9) !important; + transform: scale(0.97); } .btn-reset-quote { - color: #dceefe !important; + color: var(--glass-reset-text) !important; } .btn-reset-quote:hover { - background: rgba(105, 200, 255, 0.1) !important; - border-color: rgba(105, 200, 255, 0.32) !important; - color: #f2f8ff !important; + background: var(--glass-reset-hover-bg) !important; + border-color: var(--glass-reset-hover-border) !important; + color: var(--glass-reset-hover-text) !important; +} + +.btn-import-quote { + color: var(--glass-reset-text) !important; +} + +.btn-import-quote:hover { + background: color-mix(in srgb, var(--sky) 10%, transparent) !important; + border-color: color-mix(in srgb, var(--sky) 35%, transparent) !important; + color: var(--sky) !important; } .confirm-modal-backdrop { - background: rgba(2, 7, 15, 0.72) !important; + background: var(--glass-modal-backdrop) !important; backdrop-filter: blur(10px) saturate(125%); -webkit-backdrop-filter: blur(10px) saturate(125%); } .confirm-modal-card { - background: linear-gradient(180deg, rgba(18, 29, 46, 0.86), rgba(10, 17, 29, 0.8)) !important; + background: var(--glass-modal-bg) !important; } .pitch-inner { - background: linear-gradient(180deg, rgba(14, 25, 40, 0.72), rgba(9, 16, 28, 0.68)) !important; + background: var(--glass-pitch-bg) !important; } .pitch-title { - color: #f1f8ff !important; + color: var(--glass-heading-soft) !important; } .pitch-footer { - background: linear-gradient(135deg, rgba(11, 42, 34, 0.88), rgba(7, 28, 22, 0.86)) !important; - color: #8ee8bf !important; + background: var(--glass-pitch-footer-bg) !important; + color: var(--glass-pitch-footer-text) !important; } .mobile-panel-sheet { - background: linear-gradient(180deg, rgba(12, 21, 34, 0.92), rgba(8, 14, 24, 0.9)) !important; + background: var(--glass-mobile-sheet-bg) !important; } .mobile-panel-close-row, .mobile-panel-actions { - background: rgba(10, 18, 30, 0.84) !important; + background: var(--glass-mobile-row-bg) !important; } @media (max-width: 1100px) { .top-bar { - background: linear-gradient( - 180deg, - rgba(251, 255, 255, 0.95) 0%, - rgba(241, 247, 254, 0.91) 56%, - rgba(228, 238, 250, 0.89) 100% - ) !important; + background: var(--glass-top-bar-mobile-bg) !important; + } +} + +@media (max-width: 1100px) { + body { + background-attachment: scroll; } } @media (max-width: 600px) { body { - background: - linear-gradient(150deg, #03070f 0%, #0a1220 24%, #171226 54%, #110d18 76%, #070c14 100%), - linear-gradient(132deg, rgba(58, 154, 255, 0.16) 0%, rgba(58, 154, 255, 0) 34%), - linear-gradient(150deg, rgba(28, 201, 154, 0.12) 18%, rgba(28, 201, 154, 0) 44%), - linear-gradient(162deg, rgba(214, 68, 104, 0.11) 48%, rgba(214, 68, 104, 0) 72%), - radial-gradient(circle at 16% 12%, rgba(72, 178, 255, 0.24), transparent 24%), - radial-gradient(circle at 72% 20%, rgba(189, 58, 92, 0.18), transparent 20%), - radial-gradient(circle at 34% 46%, rgba(32, 196, 144, 0.18), transparent 22%), - radial-gradient(circle at 74% 60%, rgba(116, 82, 222, 0.16), transparent 20%); - background-attachment: fixed; + background: var(--glass-page-bg-mobile); + background-attachment: scroll; } body::before { - background: - linear-gradient(138deg, rgba(58, 154, 255, 0.14) 0%, rgba(58, 154, 255, 0) 34%), - linear-gradient(154deg, rgba(28, 201, 154, 0.1) 18%, rgba(28, 201, 154, 0) 46%), - linear-gradient(166deg, rgba(122, 84, 232, 0.1) 36%, rgba(122, 84, 232, 0) 58%), - linear-gradient(174deg, rgba(214, 68, 104, 0.1) 56%, rgba(214, 68, 104, 0) 76%); + background: var(--glass-page-overlay-mobile); opacity: 0.82; } .theme-toggle-btn { - box-shadow: 0 8px 20px rgba(6, 18, 31, 0.12) !important; + box-shadow: var(--glass-theme-toggle-mobile-shadow) !important; } .section, @@ -495,8 +613,6 @@ body::before { .sidebar, .mobile-panel-sheet, .confirm-modal-card { - box-shadow: - 0 14px 36px rgba(2, 8, 17, 0.28), - inset 0 1px 0 rgba(255, 255, 255, 0.05) !important; + box-shadow: var(--glass-mobile-panel-shadow) !important; } } diff --git a/SVS-MSP-Calculator-layout.css b/SVS-MSP-Calculator-layout.css new file mode 100644 index 0000000..461a01b --- /dev/null +++ b/SVS-MSP-Calculator-layout.css @@ -0,0 +1,183 @@ +/* SVS MSP Calculator - Layout */ +/* Extracted during Phase 5 to keep the HTML shell stable while splitting the monolithic stylesheet. */ + /* ── PAGE LAYOUT ──────────────────────────────────────────────── + .outer — CSS grid driven by shared desktop column tokens + (currently 3/5 main, 2/5 sidebar) plus shared max width + .main-col — left: sections I–VI stacked vertically + .side-col — right: sticky sidebar (desktop only; hidden ≤1100px) + Roman numeral .section-num floats LEFT outside .section via + position:absolute + a tokenized negative left offset. + This requires .section to have position:relative + a matching + tokenized left margin. + ─────────────────────────────────────────────────────────────── */ + .outer { + display: grid; + grid-template-columns: var(--layout-main-col) var(--layout-side-col); + gap: var(--layout-column-gap); + padding: var(--sidebar-top-gap) var(--page-gutter-x) 44px; + max-width: var(--page-max-width); + margin: 0 auto; + align-items: start; + } + .main-col { display: flex; flex-direction: column; gap: clamp(16px, 1.5vw, 24px); container-type: inline-size; } + .side-col { position: sticky; top: var(--sidebar-sticky-top); z-index: 10; align-self: start; } + .sidebar-utility { margin-bottom: var(--sidebar-stack-gap); display: flex; flex-direction: column; gap: 8px; } + .btn-reset-quote, + .btn-import-quote { + width: 100%; + background: var(--surface-sidebar-utility); + border: 1px solid var(--surface-sidebar-utility-border); + border-radius: var(--radius-control); + min-height: var(--control-min-height); + padding: var(--control-pad-y) var(--control-pad-x); + color: var(--muted); + font-family: 'DM Mono', monospace; + font-size: 0.75rem; + letter-spacing: 0.09em; + text-transform: uppercase; + cursor: pointer; + transition: background var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast), transform 0.1s; + } + .btn-reset-quote:active, + .btn-import-quote:active { transform: translateY(1px); } + .btn-reset-quote:hover { + background: color-mix(in srgb, var(--amber) 8%, transparent); + border-color: color-mix(in srgb, var(--amber) 38%, transparent); + color: var(--amber); + } + .btn-import-quote:hover { + background: color-mix(in srgb, var(--sky) 8%, transparent); + border-color: color-mix(in srgb, var(--sky) 38%, transparent); + color: var(--sky); + } + + .confirm-modal { + position: fixed; + inset: 0; + z-index: 400; + opacity: 0; + pointer-events: none; + transition: opacity 0.2s ease; + } + .confirm-modal.open { + opacity: 1; + pointer-events: auto; + } + .confirm-modal-backdrop { + position: absolute; + inset: 0; + background: var(--surface-backdrop); + backdrop-filter: blur(4px); + -webkit-backdrop-filter: blur(4px); + } + .confirm-modal-card { + position: relative; + width: min(460px, calc(100% - 32px)); + margin: 12vh auto 0; + background: var(--surface-modal); + border: 1px solid var(--border); + border-radius: 14px; + padding: 22px 22px 20px; + box-shadow: var(--shadow-modal); + } + .confirm-modal-eyebrow { + font-family: 'DM Mono', monospace; + font-size: 0.6875rem; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--amber); + margin-bottom: 10px; + } + .confirm-modal-title { + font-family: 'Poppins', sans-serif; + font-size: 1.5rem; + line-height: 1.3; + color: var(--ink); + margin-bottom: 10px; + } + .confirm-modal-copy { + font-size: 0.875rem; + line-height: 1.7; + color: var(--muted); + margin-bottom: 18px; + } + .confirm-modal-actions { + display: flex; + justify-content: flex-end; + gap: 10px; + } + .confirm-btn { + border-radius: var(--radius-control); + min-height: var(--control-min-height); + padding: var(--control-pad-y) var(--control-pad-x); + font-family: 'DM Mono', monospace; + font-size: 0.75rem; + letter-spacing: 0.08em; + text-transform: uppercase; + cursor: pointer; + transition: background var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast), transform 0.1s; + } + .confirm-btn:active { transform: translateY(1px); } + .confirm-btn-secondary { + background: transparent; + color: var(--muted); + border: 1px solid var(--border); + } + .confirm-btn-secondary:hover { + background: var(--surface-ghost-hover); + color: var(--ink); + border-color: var(--accent); + } + .confirm-btn-danger { + background: var(--amber); + color: #fff; + border: 1px solid transparent; + } + .confirm-btn-danger:hover { filter: brightness(1.05); } + + /* ── CLIENT BAR ───────────────────────────────────────────────── + Lives inside .main-col, above section I. + Tokenized left padding aligns "PREPARED FOR" with section card + edges and stays in sync with the current numeral gutter. + .client-input — contenteditable-style text input; oninput calls + update() which syncs clientNameDisplay in sidebar. + ─────────────────────────────────────────────────────────────── */ + .client-bar { + padding: clamp(20px, 1.8vw, 28px) 0 clamp(20px, 1.6vw, 24px) var(--section-offset); + } + .client-label { + font-family: 'DM Mono', monospace; + font-size: var(--text-label-size); + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--muted); + margin-bottom: 12px; + } + .client-input { + background: transparent; + border: none; + border-bottom: 1px solid var(--border); + color: var(--accent); + font-family: 'Poppins', sans-serif; + font-weight: 600; + font-size: clamp(1.75rem, 2vw, 1.9375rem); + width: 100%; + max-width: 560px; + outline: none; + padding: 4px 0; + } + .client-input::placeholder { color: var(--muted); opacity: 0.6; font-weight: 400; } + .client-rep-row { + margin-top: 10px; + } + .client-rep-row .client-label { + margin-bottom: 4px; + font-size: 10px; + } + .client-input--rep { + font-size: clamp(0.875rem, 1.1vw, 1rem); + font-weight: 500; + max-width: 360px; + } + + diff --git a/SVS-MSP-Calculator-light.css b/SVS-MSP-Calculator-light.css index 109c07e..0e95da0 100644 --- a/SVS-MSP-Calculator-light.css +++ b/SVS-MSP-Calculator-light.css @@ -1,255 +1,124 @@ /* ══════════════════════════════════════════════════════════════ SVS MSP Calculator — Light Theme - Imported dynamically by toggleTheme() when user switches to light mode. - Overrides :root design tokens and all hardcoded dark-mode colours - in SVS-MSP-Calculator.css. Never edit layout or structure here. + Phase 5 reduces this file to token overrides only so the light mode + stays aligned with the shared product system. ══════════════════════════════════════════════════════════════ */ -/* ── DESIGN TOKENS (light overrides) ───────────────────────────── */ :root { - --ink: #2c2825; /* soft near-black — readable without harshness */ - --paper: #ece7dc; /* warm sand/khaki page tone */ - --accent: #1a6a98; /* blue — good for buttons, kept full strength */ - --muted: #6b6360; /* mid-grey for secondary text */ - --border: #d2cbc0; /* warm border to match khaki palette */ - --card: #f1ebdf; /* general light-mode utility surface */ - --green: #217045; /* darker green — accessible on white */ - --amber: #a05f00; /* darker amber — accessible on white */ + --ink: #2c2825; + --paper: #e2dccf; + --accent: #637f88; + --muted: #6a6157; + --border: #c3baab; + --border-soft: #cdc6ba; + --card: #ece4d6; + --green: #217045; + --amber: #a05f00; + --sky: #0e7490; + --focus-ring-soft: rgba(99, 127, 136, 0.16); + --top-bar-bg: #d9d0c1; + --top-bar-border: rgba(0, 0, 0, 0.09); + --top-bar-meta: var(--muted); + --theme-chip-bg: rgba(67, 57, 50, 0.08); + --theme-chip-hover: rgba(67, 57, 50, 0.13); + --theme-chip-active: rgba(67, 57, 50, 0.18); + --theme-chip-fg: #2a2622; + --surface-section: #eee6d8; + --surface-feature: #e6ddd0; + --surface-settings: #e3d7c4; + --surface-settings-divider: #c8bcab; + --surface-input: #f1eadf; + --surface-term-wrap: #ece3d6; + --surface-term-tile: rgba(255, 255, 255, 0.04); + --surface-term-tile-hover: rgba(99, 127, 136, 0.06); + --surface-term-tile-active: linear-gradient(180deg, #829ea8 0%, #667f89 100%); + --border-term-wrap: #cabdaa; + --border-term-tile-active: rgba(82, 107, 116, 0.24); + --shadow-term-wrap: inset 0 1px 0 rgba(255,255,255,0.34); + --shadow-term-tile-active: inset 0 1px 0 rgba(255,255,255,0.18); + --text-term-name: #64594e; + --text-term-name-active: #f8f5ef; + --text-term-sub: #4d433a; + --text-term-sub-active: #f8f5ef; + --text-term-discount: #2f2a25; + --text-term-discount-active: #ffffff; + --surface-best-value: rgba(86, 146, 105, 0.12); + --border-best-value: rgba(86, 146, 105, 0.3); + --text-best-value: #35554a; + --surface-best-value-active: rgba(255, 255, 255, 0.18); + --border-best-value-active: rgba(255, 255, 255, 0.36); + --text-best-value-active: #ffffff; + --surface-sidebar: #e0dad1; + --surface-sidebar-header: #769aaa; + --surface-sidebar-body: #ebe5dd; + --surface-sidebar-utility: #d8d1c7; + --surface-export: #ddd6cd; + --surface-compare: #ddd7ce; + --surface-modal: #f0e8dc; + --surface-mobile-sheet: #e5dfd6; + --surface-mobile-close-row: #dbd4cb; + --surface-mobile-actions: #dbd4cb; + --surface-mobile-sidebar: transparent; + --surface-accent-soft: rgba(99, 127, 136, 0.09); + --surface-summary-badge: rgba(99, 127, 136, 0.09); + --border-summary-badge: rgba(99, 127, 136, 0.23); + --surface-chevron: rgba(58, 50, 43, 0.04); + --surface-chevron-active: rgba(58, 50, 43, 0.075); + --surface-ghost: rgba(58, 50, 43, 0.06); + --surface-ghost-hover: rgba(58, 50, 43, 0.1); + --surface-step: #f2ebdf; + --surface-step-hover: #e5dbcc; + --surface-step-active: var(--accent); + --surface-step-border: #a99e8f; + --text-step: var(--accent); + --surface-success: #e6f2e9; + --surface-success-border: #8fb69d; + --surface-danger: #f7e8ea; + --surface-danger-border: #d5a1ab; + --text-danger: #7a1520; + --surface-warning: #f7f0dd; + --surface-warning-panel: #f3ebda; + --surface-warning-border: #ddc39b; + --surface-compare-success: rgba(86, 146, 105, 0.12); + --surface-compare-warning: rgba(179, 133, 72, 0.11); + --surface-selected: #d6e0e1; + --surface-addon-hover: #dde2de; + --border-addon-hover: #b0bcc0; + --text-selected-accent: #264b5d; + --text-sidebar-kicker: rgba(248, 245, 239, 0.84); + --text-sidebar-heading: #fbf8f3; + --text-sidebar-placeholder: rgba(248, 245, 239, 0.76); + --text-money: var(--ink); + --text-money-hero: var(--ink); + --text-vs-heading: var(--ink); + --text-vs-accent: var(--accent); + --text-vs-muted: var(--muted); + --text-incentive: #35554a; + --text-pill-savings-active: #d4f5e0; + --section-hover-border: rgba(99, 127, 136, 0.18); + --section-hover-shadow: -3px 0 0 0 rgba(99, 127, 136, 0.18); + --section-open-border: rgba(99, 127, 136, 0.27); + --section-open-shadow: -3px 0 0 0 rgba(99, 127, 136, 0.3); + --surface-mobile-close-btn: rgba(61, 53, 46, 0.07); + --surface-mobile-close-btn-active: rgba(61, 53, 46, 0.12); + --btn-primary-fg: #fbf8f3; + --btn-primary-hover: #59737c; + --surface-pill-icon: rgba(255, 255, 255, 0.18); + --border-sidebar: #c6beb3; + --surface-sidebar-utility-border: #bfb7ad; + --border-compare: #c8c0b5; + --border-export-top: #ccc4ba; + --border-mobile-sheet: #c6beb3; + --border-mobile-row: #ccc4ba; + --sidebar-zone-services: rgba(0, 0, 0, 0.025); + --sidebar-zone-invoice: rgba(0, 0, 0, 0.04); + --sidebar-zone-value: rgba(0, 0, 0, 0.015); + --surface-switch-off: #b5ad9f; + --surface-switch-on: var(--green); } -/* ── BODY ────────────────────────────────────────────────────────── */ -body { - background: var(--paper); - color: var(--ink); -} - -/* ── TOP BAR ───────────────────────────────────────────────────── - Dark CSS sets background: var(--ink). In dark mode --ink is cream. - In light mode --ink becomes near-black, so we must pin it to cream - to keep the SVG logo (fill="#0c0c0c" text) legible. -─────────────────────────────────────────────────────────────────── */ -.top-bar { - background: #e3ddd2 !important; - border-bottom-color: rgba(0, 0, 0, 0.09) !important; /* replace strong blue stripe with soft warm separator */ -} - -/* ── SECTION CARDS ───────────────────────────────────────────────── */ -.section { - background: #f5f2ea !important; /* warm cream — floats above khaki paper */ -} - -/* ── SPLIT LIGHT-MODE SURFACES ───────────────────────────────────── - Keep sections as the main content cards. - Quote settings = warmer utility panel. - Live quote = cooler summary panel, including the mobile sheet. -*/ -.quote-settings-bar { - background: #ebe1d2 !important; - border-color: #d8cab8 !important; -} -.qs-divider { - background: #d6c8b7 !important; -} -.qs-fee-input-wrap, -.qs-fee-dollar, -.qs-fee-input { - background: #f6f0e6 !important; -} -.sidebar { - background: #edf3f6 !important; - border-color: #cfdae2 !important; -} -.sidebar-utility .btn-reset-quote, -.mobile-panel-actions .btn-reset-quote { - background: #edf3f6 !important; - border-color: #cfdae2 !important; -} -.sidebar-body { - background: #f3f7f9 !important; -} -.export-wrap { - background: #edf3f6 !important; - border-top: 1px solid #d8e2e8 !important; -} -.mobile-panel-sheet { - background: #edf3f6 !important; - border-top-color: #cfdae2 !important; -} -.mobile-panel-close-row { - background: #edf3f6 !important; - border-bottom-color: #d8e2e8 !important; -} -.mobile-panel-actions { - background: #edf3f6 !important; - border-bottom-color: #d8e2e8 !important; -} -.mobile-panel-sheet .sidebar { - background: transparent !important; -} -.mobile-panel-sheet .sidebar-body { - background: #f3f7f9 !important; -} -.confirm-modal-card { - background: #f5f2ea !important; -} -.confirm-btn-secondary:hover { - background: rgba(0, 0, 0, 0.04) !important; -} - -/* ── CHEVRON PILL — swap white-alpha tint for dark-alpha ─────────── */ -.sec-chevron { - background: rgba(0, 0, 0, 0.04) !important; -} -.sec-open .sec-chevron, -.section-toggle:hover .sec-chevron { - background: rgba(0, 0, 0, 0.07) !important; -} - -/* ── SECTION HOVER / OPEN GLOW ───────────────────────────────────── */ -.section:hover { - 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.35) !important; - box-shadow: -3px 0 0 0 rgba(26, 106, 152, 0.45) !important; -} - -/* ── CALLOUT BOXES ───────────────────────────────────────────────── */ -.callout-green { - background: #e8f7ef !important; - border-color: #3ab870 !important; - color: var(--green) !important; -} -.callout-red { - background: #fceef0 !important; - border-color: #c4526a !important; - color: #7a1520 !important; -} - -/* ── NUMBER STEPPER CONTROLS ─────────────────────────────────────── */ -/* Dark mode steppers blend in naturally. Light mode needs explicit lift: - white surfaces stand off the warm card bg; accent symbols tie to brand. */ -.step-btn { - background: #faf8f3 !important; /* soft cream — not stark white */ - border-color: #b8b4ae !important; /* stronger than --border for crispness */ - color: var(--accent) !important; /* accent blue +/- symbols instead of muted grey */ -} -.step-btn:hover { - background: #ede8de !important; /* warm tint matches khaki family on hover */ - border-color: var(--accent) !important; - color: var(--accent) !important; -} -.step-btn:active { - background: var(--accent) !important; - border-color: var(--accent) !important; - color: #fff !important; -} -.num-input { - background: #faf8f3 !important; /* soft cream — matches step buttons */ - border-color: #b8b4ae !important; -} -.num-input:focus { - border-color: var(--accent) !important; - box-shadow: 0 0 0 2px rgba(26, 106, 152, 0.15) !important; -} - -/* ── ADDON ROW SELECTED ──────────────────────────────────────────── */ -.addon-row.selected { - background: #daedf8 !important; - border-color: var(--accent) !important; - box-shadow: inset 3px 0 0 0 var(--accent) !important; -} -.addon-row.selected .addon-name { - color: var(--ink) !important; -} -.addon-row.selected .addon-price { - color: var(--accent) !important; /* override dark-mode #62c5f0 */ -} - -/* ── FEATURE CARDS ───────────────────────────────────────────────── */ -.feature-card { - background: #e9e4da !important; -} - -/* ── SIDEBAR / SUMMARY TEXT ──────────────────────────────────────── - Base dark theme hardcodes a few bright values for money and labels. - In light mode those need to return to dark text so the desktop - sidebar and the responsive mobile sheet remain readable. -*/ -.sidebar-line .val { - color: var(--ink) !important; -} -.sidebar-mrr { - color: var(--ink) !important; -} -.vs-svs-label { - color: var(--ink) !important; -} -.vs-val-accent { - color: var(--accent) !important; -} -.vs-td-muted { - color: var(--muted) !important; -} - -/* ── NUDGE BANNER ────────────────────────────────────────────────── */ -.nudge-banner.amber { - background: #fff7e0 !important; - color: var(--amber) !important; -} -.nudge-banner.green { - background: #e8f7ef !important; - color: var(--green) !important; -} -.nudge-nav-btn { - background: rgba(0, 0, 0, 0.06) !important; -} -.nudge-nav-btn:hover { - background: rgba(0, 0, 0, 0.11) !important; -} - -/* ── VS COMPARISON ───────────────────────────────────────────────── */ -.vs-comparison-wrap { - background: #e5edf2 !important; - border-color: #cfdae2 !important; -} -.vs-save-green td { background: rgba(39, 174, 96, 0.10) !important; } -.vs-save-amber td { background: rgba(210, 120, 30, 0.09) !important; } - -/* ── SUMMARY BADGE ───────────────────────────────────────────────── */ -.sec-summary-badge { - background: rgba(26, 106, 152, 0.09) !important; - border-color: rgba(26, 106, 152, 0.28) !important; -} - -/* ── MOBILE PILL HOVER ───────────────────────────────────────────── */ -.mobile-quote-pill:hover { - background: #1a5f8a !important; -} - -/* ── THEME TOGGLE BUTTON (light-mode variant) ────────────────────── */ -.theme-toggle-btn { - background: rgba(0, 0, 0, 0.09) !important; - color: #2a2622 !important; -} -.theme-toggle-btn:hover { background: rgba(0, 0, 0, 0.15) !important; } -.theme-toggle-btn:active { background: rgba(0, 0, 0, 0.21) !important; } - -/* ── SAVINGS RESULT BOX ──────────────────────────────────────────── */ -.savings-result { - background: #eaf5ef !important; - border-color: #a8d5b8 !important; -} -/* Amber warning state — JS toggles .savings-amber class */ -.savings-result.savings-amber { - background: #fff4e0 !important; - border-color: #e8c57a !important; - color: var(--amber) !important; -} - -/* ── PITCH FOOTER (green strip) ──────────────────────────────────── */ -.pitch-footer { - background: #d4eddc !important; - border-top-color: #a8d5b8 !important; +.btn-import-quote:hover { + background: color-mix(in srgb, var(--sky) 8%, transparent); + border-color: color-mix(in srgb, var(--sky) 35%, transparent); + color: var(--sky); } diff --git a/SVS-MSP-Calculator-print.css b/SVS-MSP-Calculator-print.css new file mode 100644 index 0000000..fecb5de --- /dev/null +++ b/SVS-MSP-Calculator-print.css @@ -0,0 +1,155 @@ +/* SVS MSP Calculator - Print */ +/* Extracted during Phase 5 to keep the HTML shell stable while splitting the monolithic stylesheet. */ + /* ═══════════════════════════════════════════════════════ + PRINT / PDF EXPORT (Export A) + window.print() triggers this via Print / Save PDF button. + Goals: + - Clean, branded quote document + - Hide all interactive controls + - Force all sections expanded (body shown) + - No background colours that waste ink (except header) + - Page-break control so summary never splits + ═══════════════════════════════════════════════════════ */ + @media print { + /* ── Force light background on body ── */ + body { background: var(--print-paper) !important; color: var(--print-ink) !important; font-size: 13px; } + + /* ── Hide interactive & mobile-only elements ── */ + .mobile-quote-pill, + .mobile-quote-panel, + .step-btn, + .collapsible-header, + .sec-chevron, + .section-toggle, + .tier-seg-wrap, + .pill-toggle, + .addon-row input[type=checkbox], + .savings-input-row, + .export-wrap, + .nudge-banner, + .pitch-wrap, + .quote-settings-bar, + .section-header.section-toggle { pointer-events: none; } + + .mobile-quote-pill { display: none !important; } + .mobile-quote-panel { display: none !important; } + .export-wrap { display: none !important; } + .nudge-banner { display: none !important; } + .theme-toggle-btn { display: none !important; } + .pitch-wrap { display: none !important; } + .step-btn { display: none !important; } + .collapsible-header { display: none !important; } + .sec-chevron { display: none !important; } + .sec-summary-badge { display: none !important; } + .sec-controls-row { display: none !important; } + .quote-settings-bar { display: none !important; } + .section-badge { display: none !important; } + #savingsPrompt { display: none !important; } + .quote-notes-wrap { display: none !important; } + .client-rep-row { display: none !important; } + .sidebar-focus-toggle { display: none !important; } + .sidebar-focus-print-btn { display: none !important; } + .sidebar-utility { display: none !important; } + .qs-switch { display: none !important; } + .confirm-modal { display: none !important; } + + /* ── Show ALL section bodies (force expand) ── */ + .section-body { display: block !important; } + .collapsible-body { max-height: none !important; opacity: 1 !important; overflow: visible !important; } + + /* ── Reset layout to single column ── */ + .outer { + display: block !important; + padding: 0 !important; + max-width: 100% !important; + } + .main-col, .side-col { width: 100% !important; position: static !important; } + + /* ── Top bar: keep accent, reduce height ── */ + .top-bar { + position: static !important; + padding: 10px 20px !important; + border-bottom: 2px solid var(--print-accent) !important; + background: var(--print-paper) !important; + } + .top-bar-inner { padding: 0 !important; } + .top-bar-right { color: var(--print-muted) !important; } + + /* ── Section cards: clean borders, no dark bg ── */ + .section { + background: var(--print-paper) !important; + border: 1px solid var(--print-border) !important; + box-shadow: none !important; + margin-left: 0 !important; + page-break-inside: avoid; + break-inside: avoid; + padding: 16px 20px !important; + margin-bottom: 12px !important; + } + .section-num { color: var(--print-section-num) !important; } + .section-title { font-size: 16px !important; } + + /* ── Sidebar: show inline after sections, styled for print ── */ + .sidebar { + background: var(--print-paper) !important; + border: 2px solid var(--print-accent) !important; + border-radius: 6px !important; + margin: 16px 0 !important; + page-break-inside: avoid; + break-inside: avoid; + } + .sidebar-header { background: var(--print-accent) !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; } + .sidebar-mrr { font-size: 36px !important; color: var(--print-ink) !important; } + .sidebar-line { color: var(--print-sidebar-line) !important; border-bottom-color: var(--print-border-strong) !important; } + .sidebar-line .val { color: var(--print-ink) !important; } + + /* ── VS comparison: clean for print ── */ + .vs-save-green td { background: var(--print-save-green) !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; } + .vs-save-amber td { background: var(--print-save-amber) !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; } + .vs-save-amber { background: var(--print-save-amber-panel) !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; } + + /* ── Feature cards: minimal ── */ + .feature-card { background: var(--print-feature) !important; border-color: var(--print-border-strong) !important; } + .feature-card-grid { grid-template-columns: 1fr 1fr !important; gap: 6px !important; } + + /* ── Addon rows ── */ + .addon-row { border-color: var(--print-border-strong) !important; } + .addon-row.selected { background: var(--print-addon-selected) !important; border-color: var(--print-accent) !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; } + + /* ── Callout boxes ── */ + .callout-green { background: var(--print-callout-green) !important; border-color: var(--print-callout-green-border) !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; } + .callout-red { background: var(--print-callout-red) !important; border-color: var(--print-callout-red-border) !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; } + + /* ── Progress bar ── */ + .progress-fill { -webkit-print-color-adjust: exact; print-color-adjust: exact; } + + /* ── Print footer ── */ + .pitch-footer { display: none !important; } + + /* ── Page break: force summary sidebar to start fresh ── */ + .side-col { page-break-before: always; break-before: always; } + + /* ── Input fields: show values as static text ── */ + .num-input, .qs-fee-input { + border: none !important; + background: transparent !important; + font-weight: 700 !important; + } + .client-input { + border: none !important; + background: transparent !important; + } + + /* ── Print footer note ── */ + body::after { + content: 'Prepared by Silicon Valley Services (SVS) MSP · Ottawa, Ontario · This quote is valid for 30 days from date of issue. Questions? Contact your SVS account representative.'; + display: block; + font-size: 11px; + color: var(--print-footer-note); + border-top: 1px solid var(--print-border-strong); + padding-top: 10px; + margin-top: 20px; + font-family: 'DM Mono', monospace; + } + } + diff --git a/SVS-MSP-Calculator-responsive.css b/SVS-MSP-Calculator-responsive.css new file mode 100644 index 0000000..01fb6a3 --- /dev/null +++ b/SVS-MSP-Calculator-responsive.css @@ -0,0 +1,428 @@ +/* SVS MSP Calculator - Responsive */ +/* Elastic fluid foundation — clamp() tokens in tokens.css handle continuous + scaling. Only two structural breakpoints remain: + ≤1100px — 2-col → 1-col, sidebar → mobile pill/panel + ≤ 600px — phone layout shifts (stacking, gutter collapse) + Plus one orientation rule: + ≤ 780px landscape — restore 2-col sidebar + The old 1350px and 900px breakpoints are eliminated; fluid tokens cover them. + ═══════════════════════════════════════════════════════════════════════════ */ + + /* ── TABLET / SINGLE-COLUMN (≤ 1100px) ────────────────────────── + Structural shift: grid collapses to 1fr, sidebar hides, + mobile pill + panel appear. + ─────────────────────────────────────────────────────────────── */ + @media (max-width: 1100px) { + .outer { + grid-template-columns: 1fr; + gap: 0; + } + + .pitch-inner { margin-left: 0; } + .pitch-grid { grid-template-columns: repeat(2, 1fr); } + .pitch-item:nth-child(2) { border-right: none; } + .pitch-item:nth-child(3) { border-top: 1px solid var(--border); } + .pitch-item:nth-child(4) { border-top: 1px solid var(--border); border-right: none; } + } + + /* ── PHONE (≤ 600px) ──────────────────────────────────────────── + True layout shifts only: gutter collapses, controls stack, + pill-toggles go vertical, touch targets enforced. + ─────────────────────────────────────────────────────────────── */ + @media (max-width: 600px) { + :root { + --section-offset: 0px; + } + + .top-bar-logo { margin-left: 0; } + .section { border-radius: 10px; } + + .client-bar { padding: var(--space-xl) 0 var(--space-xl) 0; } + .sections-toolbar { margin-left: 0; margin-bottom: var(--space-md); } + .client-input { font-size: 1.375rem; max-width: 100%; } + .qs-savings-stack { margin-top: var(--space-stack-tight); } + .qs-fee-row { padding: 6px 0 0; } + + .main-col > .section:first-of-type { margin-top: var(--space-sm); } + + /* Pill toggle — stack vertically on tiny screens */ + .pill-toggle { + grid-template-columns: 1fr; + } + .pill-toggle label { border-right: none; border-bottom: 1px solid var(--border); } + .pill-toggle label:last-child { border-bottom: none; } + + /* Contract terms — vertical stack on phones */ + .tier-seg { padding: var(--space-md) 6px; } + .tier-seg .tier-price { font-size: 1.125rem; } + .tier-seg .tier-name { font-size: 0.6875rem; } + .qs-term-wrap { + grid-template-columns: 1fr; + } + .qs-term-wrap .tier-seg { + padding: var(--space-stack) var(--space-stack) 13px; + border-right: none; + border-bottom: 1px solid var(--border); + text-align: left; + } + .qs-term-wrap .tier-seg:last-of-type { + border-bottom: none; + } + .qs-term-wrap .tier-name { font-size: 0.75rem; margin-bottom: var(--space-xs); } + .qs-term-wrap .tier-sub { font-size: 0.6875rem; } + .qs-toggle-row.qs-fee-waive { padding: 6px 9px; } + + /* Input rows — stack label above input */ + .input-row { + flex-direction: column; + align-items: flex-start; + gap: var(--space-md); + } + .section-body .num-stepper { width: 100%; } + .section-body .num-input { width: 100%; font-size: 1.25rem; padding: var(--space-md); flex: 1; } + .section-body .step-btn { width: 48px; font-size: 1.375rem; } + + /* Section titles — tighter on phone */ + .section-title { + font-size: 1.1rem; + } + .section-num { + font-size: 1rem; + } + + /* Controls row — stack full-width on phone */ + .sec-controls-row { + flex-direction: column; + gap: 6px; + } + .sec-controls-row .num-stepper { + width: 100%; + max-width: none; + } + .sec-controls-row .num-input { + flex: 1 1 0%; + width: auto; + min-width: 0; + } + .sec-controls-row .step-btn { + width: 40px; + flex-shrink: 0; + } + .section .sec-controls-row > .section-badge, + .section .sec-controls-row > .sec-summary-badge { + width: 100%; + max-width: none; + align-self: stretch; + justify-content: center; + min-height: 36px; + } + + /* Collapsible */ + .collapsible-body { padding: var(--space-sm) 0 var(--space-stack-tight) var(--space-stack-roomy); } + + /* Feature cards — single col already, just tighter */ + .feature-card { padding: var(--space-stack) var(--space-stack-roomy); } + .m365-app-strip { padding: var(--space-stack) var(--space-stack-roomy) var(--space-md); } + .m365-app-list { + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: var(--space-stack-tight); + } + .m365-app-item { padding: var(--space-stack-tight) 6px; } + .m365-app-icon { + width: 15px; + height: 15px; + } + + /* Savings row — stack */ + .savings-input-row { flex-direction: column; align-items: flex-start; gap: var(--space-sm); } + .savings-input-row input { width: 100%; } + + /* Sidebar */ + .sidebar-body { padding: var(--space-lg); } + .sidebar-header { padding: var(--space-stack) var(--space-xl); } + .sidebar-mrr { font-size: 2.25rem; } + + /* VS table — keep readable while fitting the mobile sidebar panel */ + .vs-comparison-wrap { padding: var(--space-lg) var(--space-stack-roomy); } + .vs-header { gap: var(--space-sm); margin-bottom: var(--space-stack); } + .vs-brand-name { font-size: 0.9375rem; } + .vs-table td { padding: var(--space-sm) 3px; font-size: 0.78125rem; } + .vs-save-row td { padding: var(--space-stack-tight) var(--space-md); } + .vs-footnote { font-size: 0.65625rem; line-height: 1.55; } + + /* Pitch footer */ + .pitch-wrap { padding: 0; } + .pitch-inner { margin-left: 0; border-radius: 0; } + .pitch-grid { grid-template-columns: 1fr 1fr; } + .pitch-item { padding: var(--space-xl) var(--space-stack-roomy); } + .pitch-item:nth-child(2) { border-right: none; } + .pitch-item:nth-child(3) { border-top: 1px solid var(--border); } + .pitch-item:nth-child(4) { border-top: 1px solid var(--border); border-right: none; } + .pitch-title { font-size: 0.875rem; } + .pitch-desc { font-size: 0.8125rem; } + .pitch-footer { padding: var(--space-stack) var(--space-stack-roomy); font-size: 0.75rem; } + + /* Touch targets — ensure ≥44px on phone */ + .collapsible-header { + min-height: 44px; + } + .section-toggle { + min-height: 44px; + } + + /* Nudge banner */ + .nudge-banner { padding: var(--space-stack) var(--space-lg); font-size: 0.8125rem; min-height: 0; } + .export-wrap { padding: var(--space-stack-roomy) var(--space-stack-roomy) var(--space-lg); } + .confirm-modal-card { + margin-top: 8vh; + padding: var(--space-xl) var(--space-lg) var(--space-lg); + } + .confirm-modal-title { font-size: 1.3125rem; } + .confirm-modal-actions { flex-direction: column-reverse; } + .confirm-btn { width: 100%; } + + /* Fee table */ + .fee-table td { padding: 7px 0; font-size: 0.8125rem; } + } + + /* ── LANDSCAPE PHONE (≤ 780px, orientation: landscape) ── */ + @media (max-width: 780px) and (orientation: landscape) { + .outer { + grid-template-columns: 1fr 1fr; + gap: var(--space-2xl); + padding: var(--space-xl) var(--space-xl) 40px; + align-items: start; + } + .main-col { order: 1; } + .side-col { + order: 2; + position: sticky; + top: 60px; + align-self: start; + } + .section { + margin-left: 0; + padding: var(--space-lg) var(--space-xl) 22px; + } + .client-bar { padding: var(--space-stack-roomy) 0 var(--space-stack-roomy) 0; } + .sidebar { margin-top: 0; } + .sidebar-mrr { font-size: 1.875rem; } + .pitch-grid { grid-template-columns: repeat(2, 1fr); } + .pitch-inner { margin-left: 0; } + .pitch-wrap { padding: 0; } + } + + /* ── MOBILE-ONLY ELEMENTS — hidden at desktop baseline ───────── + MUST be display:none here (outside any media query) so that + the panel doesn't render on top of desktop layout. + The @media (max-width:1100px) block below overrides to display:flex. + ─────────────────────────────────────────────────────────────── */ + .mobile-quote-pill { display: none; } + .mobile-quote-panel { display: none; } + .mobile-panel-actions { display: none; } + + /* ═══════════════════════════════════════ + MOBILE QUOTE PILL + FULL-SCREEN PANEL + ═══════════════════════════════════════ */ + + + @media (max-width: 1100px) { + .sidebar-focus-toggle, + .sidebar-focus-backdrop { display: none; } + + /* Hide the static sidebar entirely on mobile/tablet */ + .side-col { display: none; } + + /* Show the floating pill */ + .mobile-quote-pill { + display: flex; + align-items: center; + gap: var(--space-stack-tight); + position: fixed; + top: 82px; + right: max(14px, env(safe-area-inset-right, 0px)); + z-index: 200; + background: var(--accent); + color: var(--btn-primary-fg); + border-radius: 50px; + padding: var(--space-stack-tight) var(--space-lg) var(--space-stack-tight) var(--space-stack); + cursor: pointer; + box-shadow: var(--shadow-floating); + border: none; + font-family: 'DM Mono', monospace; + font-size: 15px; + font-weight: 500; + letter-spacing: 0.04em; + transition: background var(--transition-fast), transform var(--transition-fast); + user-select: none; + -webkit-tap-highlight-color: transparent; + } + .mobile-quote-pill:active { transform: scale(0.96); } + .mobile-quote-pill:hover { background: var(--btn-primary-hover); } + .mobile-pill-icon { + width: 28px; + height: 28px; + background: var(--surface-pill-icon); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + } + .mobile-pill-mrr { + font-family: 'DM Mono', monospace; + font-size: 16px; + font-weight: 500; + line-height: 1; + } + .mobile-pill-label { + font-size: 10px; + opacity: 0.75; + letter-spacing: 0.1em; + text-transform: uppercase; + line-height: 1; + margin-top: 2px; + } + + /* Full-screen overlay panel */ + .mobile-quote-panel { + position: fixed; + inset: 0; + z-index: 300; + display: flex; + flex-direction: column; + pointer-events: none; + opacity: 0; + transition: opacity 0.25s ease; + } + .mobile-quote-panel.open { + pointer-events: all; + opacity: 1; + } + + /* Dark backdrop */ + .mobile-panel-backdrop { + position: absolute; + inset: 0; + background: var(--surface-mobile-backdrop); + backdrop-filter: blur(3px); + -webkit-backdrop-filter: blur(3px); + } + + /* Slide-up sheet */ + .mobile-panel-sheet { + position: absolute; + bottom: 0; + left: 0; + right: 0; + max-height: 100vh; + background: var(--surface-mobile-sheet); + border-radius: 0; + overflow-y: auto; + overscroll-behavior: contain; + -webkit-overflow-scrolling: touch; + transform: translateY(100%); + transition: transform 0.3s cubic-bezier(0.32, 0.72, 0, 1); + will-change: transform; + border-top: 1px solid var(--border-mobile-sheet); + padding-bottom: env(safe-area-inset-bottom, 0px); + } + .mobile-quote-panel.open .mobile-panel-sheet { + transform: translateY(0); + } + + /* Drag handle */ + .mobile-panel-handle { + width: 40px; + height: 4px; + background: var(--border); + border-radius: 2px; + margin: var(--space-stack) auto 0; + flex-shrink: 0; + } + + /* Close button row */ + .mobile-panel-close-row { + display: flex; + align-items: center; + justify-content: space-between; + padding: var(--space-stack-roomy) var(--space-xl) var(--space-md); + border-bottom: 1px solid var(--border-mobile-row); + background: var(--surface-mobile-close-row); + } + .mobile-panel-actions { + display: block; + padding: 0 var(--space-xl) var(--space-md); + border-bottom: 1px solid var(--border-mobile-row); + background: var(--surface-mobile-actions); + } + .mobile-panel-actions .btn-export { + margin-top: var(--space-md); + } + .mobile-panel-actions .btn-export-secondary { + margin-top: 6px; + } + .mobile-panel-close-title { + font-family: 'DM Mono', monospace; + font-size: 12px; + text-transform: uppercase; + letter-spacing: 0.12em; + color: var(--muted); + } + .mobile-panel-close-btn { + background: var(--surface-mobile-close-btn); + border: none; + color: var(--ink); + border-radius: 50%; + width: 44px; + height: 44px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + font-size: 22px; + line-height: 1; + flex-shrink: 0; + -webkit-tap-highlight-color: transparent; + transition: background var(--transition-fast); + } + .mobile-panel-close-btn:active { background: var(--surface-mobile-close-btn-active); } + + /* Touch targets — minimum 44px on mobile per WCAG */ + .nudge-nav-btn { + width: 44px; + height: 44px; + } + + /* Sidebar inside the mobile sheet — strip all desktop positioning */ + .mobile-panel-sheet .sidebar { + margin-top: 0 !important; + border-radius: 0 !important; + border: none !important; + box-shadow: none !important; + overflow: visible !important; + background: var(--surface-mobile-sidebar) !important; + } + /* Keep Live Quote header visible in responsive panel so + Insight can sit directly below it (matching desktop order). */ + .mobile-panel-sheet .sidebar-header { + display: block !important; + } + .mobile-panel-sheet .sidebar-body { + padding-top: 0 !important; + } + .mobile-panel-sheet .nudge-banner { + margin-bottom: 35px; + } + } + + /* Landscape phone — restore the static sidebar and suppress the mobile sheet. */ + @media (max-width: 780px) and (orientation: landscape) { + .side-col { display: block; } + .mobile-quote-pill, + .mobile-quote-panel, + .mobile-panel-actions { + display: none; + } + .mobile-panel-sheet { max-height: 88vh; } + } diff --git a/SVS-MSP-Calculator-tokens.css b/SVS-MSP-Calculator-tokens.css new file mode 100644 index 0000000..d9dddfe --- /dev/null +++ b/SVS-MSP-Calculator-tokens.css @@ -0,0 +1,239 @@ +/* SVS MSP Calculator - Tokens */ +/* Extracted during Phase 5 to keep the HTML shell stable while splitting the monolithic stylesheet. */ + *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } + + /* ── THEME TRANSITION ───────────────────────────────────────── + Brief color fade when switching themes so the swap feels smooth + instead of a jarring flash. Applied to body so it cascades. + transition-duration kept short (0.25s) to feel snappy. + ─────────────────────────────────────────────────────────────── */ + body.theme-transitioning, + body.theme-transitioning *, + body.theme-transitioning *::before, + body.theme-transitioning *::after { + transition: background-color 0.25s ease, color 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease !important; + } + + /* ── FOCUS VISIBLE ────────────────────────────────────────────── + Single rule covers all interactive elements — native inputs, + custom div toggles (section headers, collapsible headers), + addon rows, tier segments, and the theme toggle button. + Uses :focus-visible so mouse clicks don't show the ring. + ─────────────────────────────────────────────────────────────── */ + :focus-visible { + outline: 2px solid var(--accent); + outline-offset: 2px; + } + /* Suppress the default outline on elements we've styled explicitly */ + .num-input:focus-visible, + .client-input:focus-visible, + .qs-fee-input:focus-visible, + .savings-input-row input:focus-visible { + outline: none; + border-color: var(--accent); + box-shadow: 0 0 0 2px var(--focus-ring-soft); + } + /* ── DESIGN TOKENS ───────────────────────────────────────────── + Single source of truth for all colours. Edit here, not inline. + ─────────────────────────────────────────────────────────────── */ + html { + font-size: calc(16px * var(--font-scale, 1)); + } + + :root { + --font-scale: 1.03; + --page-max-width: clamp(1200px, 92vw, 2400px); + --page-gutter-x: clamp(16px, 3vw, 80px); + --layout-main-col: minmax(0, 3fr); + --layout-side-col: minmax(360px, 2fr); + --layout-column-gap: clamp(24px, 3vw, 56px); + --section-offset: clamp(52px, 7vw, 104px); + --section-num-width: clamp(44px, 5.5vw, 84px); + --section-num-size: clamp(2.625rem, 3.4vw, 4.125rem); + --section-padding-x: clamp(18px, 2.5vw, 40px); + --section-padding-top: clamp(20px, 2vw, 28px); + --section-padding-bottom: clamp(24px, 2.2vw, 32px); + --space-xs: 4px; + --space-sm: 8px; + --space-stack-tight: 10px; + --space-md: 12px; + --space-stack: 14px; + --space-stack-roomy: 16px; + --space-lg: 18px; + --space-xl: 20px; + --space-2xl: 24px; + --space-3xl: 28px; + --space-4xl: 32px; + --radius-control: 6px; + --radius-card: 12px; + --control-min-height: 46px; + --control-pad-y: 10px; + --control-pad-x: 16px; + --control-pad-y-tight: 6px; + --control-pad-x-tight: 10px; + --content-measure: 68ch; + --text-body-size: 1.03125rem; + --text-body-line: 1.72; + --text-meta-size: 0.75rem; + --text-label-size: 0.75rem; + --text-copy-size: 0.9375rem; + --text-copy-line: 1.76; + --text-compact-line: 1.58; + --text-title-line: 1.24; + --ink: #e8e3da; /* warm beige-white — brighter for legibility */ + --paper: #1c1a17; /* darker base — widens gap vs card for panel float */ + --accent: #3d8aba; /* lifted blue — pops on dark backgrounds */ + --muted: #9e9588; /* softer secondary — clearly subordinate but readable */ + --border: #35322c; /* subtler dividers */ + --border-soft: var(--border); + --card: #272420; /* elevated surface — clear separation from paper */ + --green: #3ab870; + --amber: #e8920f; + --sky: #38bdf8; + --transition-fast: 0.15s; + --transition-medium: 0.25s; + --focus-ring-soft: rgba(45,122,168,0.25); + --top-bar-bg: var(--ink); + --top-bar-border: var(--accent); + --top-bar-meta: var(--muted); + --top-bar-shadow: 0 10px 24px rgba(0,0,0,0.08); + --theme-chip-bg: rgba(0, 0, 0, 0.1); + --theme-chip-hover: rgba(0, 0, 0, 0.17); + --theme-chip-active: rgba(0, 0, 0, 0.23); + --theme-chip-fg: #3a3632; + --theme-chip-border: transparent; + --theme-chip-shadow: none; + --surface-section: var(--card); + --surface-feature: var(--card); + --surface-settings: var(--card); + --surface-settings-divider: var(--border); + --surface-input: var(--card); + --surface-term-wrap: var(--surface-input); + --surface-term-tile: transparent; + --surface-term-tile-hover: var(--surface-accent-soft); + --surface-term-tile-active: linear-gradient(180deg, color-mix(in srgb, var(--accent) 60%, white 12%), color-mix(in srgb, var(--accent) 72%, black 28%)); + --border-term-wrap: var(--border); + --border-term-tile-active: transparent; + --shadow-term-wrap: inset 0 1px 0 color-mix(in srgb, var(--ink) 5%, transparent); + --shadow-term-tile-active: inset 0 1px 0 color-mix(in srgb, white 14%, transparent); + --text-term-name: var(--muted); + --text-term-name-active: var(--text-on-accent); + --text-term-sub: var(--muted); + --text-term-sub-active: var(--text-on-accent-strong); + --text-term-discount: color-mix(in srgb, var(--ink) 84%, var(--muted)); + --text-term-discount-active: #ffffff; + --surface-best-value: var(--surface-positive-badge-strong); + --border-best-value: var(--border-positive-badge-strong); + --text-best-value: var(--green); + --surface-best-value-active: var(--surface-on-accent-badge); + --border-best-value-active: var(--border-on-accent-badge); + --text-best-value-active: var(--text-on-accent); + --surface-sidebar: var(--card); + --border-sidebar: var(--border); + --surface-sidebar-body: transparent; + --surface-sidebar-header: #5c8097; + --surface-sidebar-utility: var(--card); + --surface-sidebar-utility-border: var(--border); + --surface-export: var(--card); + --border-export-top: transparent; + --surface-compare: rgba(255, 255, 255, 0.06); + --border-compare: var(--border); + --surface-modal: var(--card); + --surface-mobile-sheet: var(--card); + --border-mobile-sheet: var(--border-soft); + --surface-mobile-close-row: transparent; + --surface-mobile-actions: var(--card); + --border-mobile-row: var(--border-soft); + --surface-mobile-sidebar: var(--surface-sidebar); + --surface-mobile-backdrop: rgba(0,0,0,0.65); + --surface-accent-soft: rgba(45, 122, 168, 0.07); + --surface-summary-badge: rgba(45,122,168,0.12); + --border-summary-badge: rgba(45,122,168,0.3); + --surface-chevron: rgba(255,255,255,0.05); + --surface-chevron-active: rgba(255,255,255,0.08); + --surface-chevron-mobile: var(--surface-chevron-active); + --surface-ghost: rgba(255,255,255,0.08); + --surface-ghost-hover: rgba(255,255,255,0.15); + --surface-step: var(--card); + --surface-step-hover: var(--border); + --surface-step-active: var(--accent); + --surface-step-border: var(--border); + --text-step: var(--muted); + --surface-success: #162e22; + --surface-success-border: #245840; + --surface-danger: #2a1319; + --surface-danger-border: #5e2830; + --text-danger: #e87882; + --surface-warning: #2a1e06; + --surface-warning-panel: #2e1f08; + --surface-warning-border: #5a3a10; + --surface-compare-success: rgba(39, 174, 96, 0.16); + --surface-compare-warning: rgba(210, 120, 30, 0.16); + --surface-selected: #1d2d3a; + --text-selected-accent: #ccecff; + --surface-positive-pill: rgba(33,112,69,0.10); + --surface-positive-badge: rgba(33,112,69,0.12); + --border-positive-badge: rgba(33,112,69,0.28); + --surface-positive-badge-strong: rgba(33,112,69,0.13); + --border-positive-badge-strong: rgba(33,112,69,0.3); + --surface-positive-panel: rgba(33,112,69,0.08); + --border-positive-panel: rgba(33,112,69,0.22); + --surface-addon-hover: var(--surface-accent-soft); + --border-addon-hover: color-mix(in srgb, var(--accent) 24%, var(--border)); + --text-sidebar-kicker: rgba(255,255,255,0.75); + --text-sidebar-heading: #fff; + --text-sidebar-placeholder: rgba(255,255,255,0.65); + --text-money: #f2ede4; + --text-money-hero: #f5f0e8; + --text-vs-heading: #f2ede4; + --text-vs-accent: #5aaedc; + --text-vs-muted: #b5ab9e; + --text-incentive: var(--green); + --text-on-accent: #fff; + --text-on-accent-strong: rgba(255,255,255,0.9); + --text-on-accent-soft: rgba(255,255,255,0.85); + --text-on-accent-muted: rgba(255,255,255,0.8); + --text-on-accent-subtle: rgba(255,255,255,0.7); + --surface-on-accent-badge: rgba(255,255,255,0.18); + --border-on-accent-badge: rgba(255,255,255,0.35); + --text-pill-savings-active: #86efac; + --surface-backdrop: rgba(0, 0, 0, 0.62); + --shadow-modal: 0 16px 50px rgba(0,0,0,0.35); + --shadow-switch-knob: 0 1px 3px rgba(0,0,0,0.3); + --shadow-floating: 0 4px 20px rgba(0,0,0,0.45); + --section-hover-border: rgba(45,122,168,0.35); + --section-hover-shadow: -3px 0 0 0 rgba(45,122,168,0.4); + --section-open-border: rgba(45,122,168,0.5); + --section-open-shadow: -3px 0 0 0 rgba(45,122,168,0.7); + --surface-switch-knob: #fff; + --surface-switch-off: #4a4540; + --surface-switch-on: var(--green); + --surface-mobile-close-btn: var(--border); + --surface-mobile-close-btn-active: var(--muted); + --btn-primary-fg: #fff; + --btn-primary-hover: #3a8fc4; + --surface-pill-icon: rgba(255,255,255,0.2); + --print-paper: #fff; + --print-ink: #1a1a1a; + --print-accent: #2d7aa8; + --print-muted: #555; + --print-border: #ccc; + --print-border-strong: #ddd; + --print-section-num: #bbb; + --print-sidebar-line: #444; + --print-save-green: #e8f5e9; + --print-save-amber: #fff3e0; + --print-save-amber-panel: #fff8e1; + --print-feature: #f9f9f9; + --print-addon-selected: #e8f4fb; + --print-callout-green: #f0faf4; + --print-callout-red: #fff0f0; + --print-callout-green-border: #3ab870; + --print-callout-red-border: #5e2830; + --print-footer-note: #888; + --sidebar-stack-gap: 14px; + --sidebar-top-gap: calc(var(--sidebar-stack-gap) + 14px); + --top-bar-sticky-offset: 62px; + --sidebar-sticky-top: calc(var(--top-bar-sticky-offset) + var(--sidebar-top-gap)); + } + diff --git a/SVS-MSP-Calculator.css b/SVS-MSP-Calculator.css index 4c390b3..9449940 100644 --- a/SVS-MSP-Calculator.css +++ b/SVS-MSP-Calculator.css @@ -1,2095 +1,10 @@ - *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } - - /* ── FOCUS VISIBLE ────────────────────────────────────────────── - Single rule covers all interactive elements — native inputs, - custom div toggles (section headers, collapsible headers), - addon rows, tier segments, and the theme toggle button. - Uses :focus-visible so mouse clicks don't show the ring. - ─────────────────────────────────────────────────────────────── */ - :focus-visible { - outline: 2px solid var(--accent); - outline-offset: 2px; - } - /* Suppress the default outline on elements we've styled explicitly */ - .num-input:focus-visible, - .client-input:focus-visible, - .qs-fee-input:focus-visible, - .savings-input-row input:focus-visible { - outline: none; - border-color: var(--accent); - box-shadow: 0 0 0 2px rgba(45,122,168,0.25); - } - /* ── DESIGN TOKENS ───────────────────────────────────────────── - Single source of truth for all colours. Edit here, not inline. - ─────────────────────────────────────────────────────────────── */ - :root { - --ink: #e8e3da; /* warm beige-white — brighter for legibility */ - --paper: #1c1a17; /* darker base — widens gap vs card for panel float */ - --accent: #3d8aba; /* lifted blue — pops on dark backgrounds */ - --muted: #9e9588; /* softer secondary — clearly subordinate but readable */ - --border: #35322c; /* subtler dividers */ - --card: #272420; /* elevated surface — clear separation from paper */ - --green: #3ab870; - --amber: #e8920f; - --sidebar-stack-gap: 12px; - --sidebar-top-gap: calc(var(--sidebar-stack-gap) + 20px); - --top-bar-sticky-offset: 62px; - --sidebar-sticky-top: calc(var(--top-bar-sticky-offset) + var(--sidebar-top-gap)); - } - body { - background: var(--paper); - color: var(--ink); - font-family: 'Lato', sans-serif; - font-size: 16px; - line-height: 1.75; - min-height: 100vh; - } - - /* ── TOP BAR ──────────────────────────────────────────────────── - Sticky header. z-index:100 sits below mobile panel (z:300) - and mobile pill (z:200). Background is --ink (cream) not --paper. - Contains: SVS logo SVG (inline) | quote ref + date (DM Mono). - ─────────────────────────────────────────────────────────────── */ - .top-bar { - position: sticky; - top: 0; - z-index: 100; - background: var(--ink); - border-bottom: 2px solid var(--accent); - padding: 14px 0; - display: flex; - justify-content: center; - } - .top-bar-inner { - width: 100%; - max-width: 1600px; - padding: 0 clamp(20px,2vw,40px); - display: flex; - align-items: center; - justify-content: space-between; - } - .top-bar-logo { margin-left: 70px; flex-shrink: 0; } - .top-bar-right { - font-family: 'DM Mono', monospace; - font-size: 12px; - letter-spacing: 0.07em; - color: var(--muted); - text-align: right; - line-height: 1.6; - margin-left: auto; - } - - /* ── THEME TOGGLE BUTTON ──────────────────────────────────────── - Sits to the right of the quote ref/date in .top-bar-inner. - Slightly darker chip vs the cream top-bar bg so it reads as - a distinct control, not noise. Works on both theme top-bars. - ─────────────────────────────────────────────────────────────── */ - .theme-toggle-btn { - background: rgba(0, 0, 0, 0.1); /* ~#c9c5bc chip on cream bar */ - border: none; - border-radius: 8px; - width: 36px; - height: 36px; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - color: #3a3632; - transition: background 0.15s; - flex-shrink: 0; - margin-left: 14px; - } - .theme-toggle-btn:hover { background: rgba(0, 0, 0, 0.17); } - .theme-toggle-btn:active { background: rgba(0, 0, 0, 0.23); } - .theme-toggle-btn svg { display: block; } - - /* ── PAGE LAYOUT ──────────────────────────────────────────────── - .outer — CSS grid, 3fr main / 2fr sidebar, max 1600px - .main-col — left: sections I–VI stacked vertically - .side-col — right: sticky sidebar (desktop only; hidden ≤1100px) - Roman numeral .section-num floats LEFT outside .section via - position:absolute + negative left offset (left: -96px). - This requires .section to have position:relative + margin-left:96px. - ─────────────────────────────────────────────────────────────── */ - .outer { - display: grid; - grid-template-columns: 3fr 2fr; - gap: 52px; - padding: var(--sidebar-top-gap) clamp(20px,2vw,40px) 52px; - max-width: 1600px; - margin: 0 auto; - align-items: start; - } - .main-col { display: flex; flex-direction: column; gap: 28px; } - .side-col { position: sticky; top: var(--sidebar-sticky-top); z-index: 10; align-self: start; } - .sidebar-utility { margin-bottom: var(--sidebar-stack-gap); } - .btn-reset-quote { - width: 100%; - background: var(--card); - border: 1px solid var(--border); - border-radius: 10px; - padding: 11px 14px; - color: var(--muted); - font-family: 'DM Mono', monospace; - font-size: 12px; - letter-spacing: 0.09em; - text-transform: uppercase; - cursor: pointer; - transition: background 0.15s, border-color 0.15s, color 0.15s, transform 0.1s; - } - .btn-reset-quote:hover { - background: rgba(232, 146, 15, 0.08); - border-color: rgba(232, 146, 15, 0.38); - color: var(--amber); - } - .btn-reset-quote:active { transform: translateY(1px); } - - .confirm-modal { - position: fixed; - inset: 0; - z-index: 400; - opacity: 0; - pointer-events: none; - transition: opacity 0.2s ease; - } - .confirm-modal.open { - opacity: 1; - pointer-events: auto; - } - .confirm-modal-backdrop { - position: absolute; - inset: 0; - background: rgba(0, 0, 0, 0.62); - backdrop-filter: blur(4px); - -webkit-backdrop-filter: blur(4px); - } - .confirm-modal-card { - position: relative; - width: min(460px, calc(100% - 32px)); - margin: 12vh auto 0; - background: var(--card); - border: 1px solid var(--border); - border-radius: 14px; - padding: 22px 22px 20px; - box-shadow: 0 16px 50px rgba(0,0,0,0.35); - } - .confirm-modal-eyebrow { - font-family: 'DM Mono', monospace; - font-size: 11px; - letter-spacing: 0.12em; - text-transform: uppercase; - color: var(--amber); - margin-bottom: 10px; - } - .confirm-modal-title { - font-family: 'Poppins', sans-serif; - font-size: 24px; - line-height: 1.3; - color: var(--ink); - margin-bottom: 10px; - } - .confirm-modal-copy { - font-size: 14px; - line-height: 1.7; - color: var(--muted); - margin-bottom: 18px; - } - .confirm-modal-actions { - display: flex; - justify-content: flex-end; - gap: 10px; - } - .confirm-btn { - border-radius: 8px; - padding: 11px 14px; - font-family: 'DM Mono', monospace; - font-size: 12px; - letter-spacing: 0.08em; - text-transform: uppercase; - cursor: pointer; - transition: background 0.15s, border-color 0.15s, color 0.15s, transform 0.1s; - } - .confirm-btn:active { transform: translateY(1px); } - .confirm-btn-secondary { - background: transparent; - color: var(--muted); - border: 1px solid var(--border); - } - .confirm-btn-secondary:hover { - background: rgba(255,255,255,0.05); - color: var(--ink); - border-color: var(--accent); - } - .confirm-btn-danger { - background: var(--amber); - color: #fff; - border: 1px solid transparent; - } - .confirm-btn-danger:hover { filter: brightness(1.05); } - - /* ── CLIENT BAR ───────────────────────────────────────────────── - Lives inside .main-col, above section I. - padding-left:96px aligns "PREPARED FOR" with section card edges - (matching the 96px margin-left on .section). - .client-input — contenteditable-style text input; oninput calls - update() which syncs clientNameDisplay in sidebar. - ─────────────────────────────────────────────────────────────── */ - .client-bar { - padding: 32px 0 32px 96px; - } - .client-label { - font-family: 'DM Mono', monospace; - font-size: 13px; - letter-spacing: 0.12em; - text-transform: uppercase; - color: var(--muted); - margin-bottom: 10px; - } - .client-input { - background: transparent; - border: none; - border-bottom: 1px solid var(--border); - color: var(--accent); - font-family: 'Poppins', sans-serif; - font-weight: 600; - font-size: 30px; - width: 100%; - max-width: 480px; - outline: none; - padding: 2px 0; - } - .client-input::placeholder { color: var(--muted); opacity: 0.6; font-weight: 400; } - - /* ── SECTION CARDS (I–VI) ─────────────────────────────────────── - Each section = position:relative card with: - .section-num — absolute, floats left outside card (Cinzel) - .section-header — flex row: title-block | summary badge | chevron - .section-body — collapsible content (overflow:hidden, JS toggle) - JS toggleSection(id) adds/removes .sec-open class on .section. - .sec-open .sec-chevron rotates 180deg (down→up arrow). - .sec-summary-badge is shown/hidden by setSummary() in update(). - ─────────────────────────────────────────────────────────────── */ - .section { - position: relative; - margin-left: 96px; - border-radius: 12px; - border: 1px solid var(--border); - background: var(--card); /* elevated above paper — was #272420 hardcoded */ - padding: 32px 36px 36px; - } - .main-col > .section:first-of-type { margin-top: 24px; } - .section-header { - display: flex; - align-items: flex-start; - gap: 12px; - margin-bottom: 32px; - } - .section:not(.sec-open) .section-header { margin-bottom: 0; } - .section-num { - font-family: 'Cinzel', serif; - font-weight: 700; - font-size: 62px; - line-height: 1; - color: var(--border); - flex-shrink: 0; - width: 80px; - user-select: none; - position: absolute; - left: -96px; - top: 32px; - text-align: right; - } - .section-title-block { flex: 1; min-width: 0; } - .section-title { - font-family: 'Poppins', sans-serif; - font-size: 24px; - font-weight: 600; - color: var(--ink); - line-height: 1.3; - word-break: break-word; - } - .section-title-tag { font-size: 15px; font-weight: 400; opacity: 0.6; } - .section-subtitle { - font-size: 14px; - color: var(--muted); - margin-top: 6px; - line-height: 1.55; - } - .section-badge { - font-family: 'DM Mono', monospace; - font-size: 13px; - text-transform: uppercase; - letter-spacing: 0.1em; - padding: 3px 8px; - border: 1px solid var(--border); - border-radius: 2px; - color: var(--muted); - display: inline-block; - margin-top: 8px; - } - .section-toggle { cursor: pointer; user-select: none; } - .sec-chevron { - display: flex; - align-items: center; - justify-content: center; - color: var(--muted); - transition: transform 0.25s ease, color 0.15s; - flex-shrink: 0; - transform: rotate(0deg); - width: 34px; - height: 34px; - background: rgba(255,255,255,0.05); - border-radius: 6px; - margin-top: 2px; - } - .sec-open .sec-chevron { transform: rotate(180deg); color: var(--ink); background: rgba(255,255,255,0.08); } - .section-toggle:hover .sec-chevron { color: var(--ink); background: rgba(255,255,255,0.08); } - .sec-chevron svg { display: block; } - .section-body { overflow: hidden; } - - /* ── SECTION SUMMARY BADGE ────────────────────────────────────── - Shown only when section is COLLAPSED (display:none by default). - JS: setSummary(id, text) sets textContent + display:inline-block - when collapsed(secId) && !!text. Hidden when section is open. - On mobile (≤600px) placed in grid col 2 row 1 (top-right of header). - ─────────────────────────────────────────────────────────────── */ - .sec-summary-badge { - display: none; - font-family: 'DM Mono', monospace; - font-size: 13px; - letter-spacing: 0.08em; - color: var(--accent); - background: rgba(45,122,168,0.12); - border: 1px solid rgba(45,122,168,0.3); - border-radius: 6px; - padding: 5px 11px; - white-space: nowrap; - flex-shrink: 0; - margin-top: 2px; - } - - /* ── COLLAPSED SECTION COUNTER (sec-02/03/04 when collapsed) ─── - Sits inside .section-title-block below .section-badge. - Two square .sec-count-btn buttons with a small gap between them. - Visible only when the section is collapsed (not .sec-open). - Buttons call stepCount() which stops propagation. - ─────────────────────────────────────────────────────────────── */ - .sec-collapsed-counter { - display: flex; - align-items: center; - gap: 6px; - margin-top: 12px; - } - .sec-count-btn { - width: 44px; - height: 44px; - background: var(--card); - border: 1px solid var(--border); - border-radius: 6px; - color: var(--muted); - font-size: 22px; - line-height: 1; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - padding: 0; - flex-shrink: 0; - user-select: none; - transition: background 0.12s, color 0.12s, border-color 0.12s; - } - .sec-count-btn:hover { background: var(--border); color: var(--ink); } - .sec-count-btn:active { background: var(--accent); color: #fff; border-color: var(--accent); } - - /* ── PILL TOGGLE (Section II — M365 vs BYOL) ─────────────────── - CSS-only toggle using hidden radio inputs + adjacent label styling. - input:checked + label gets accent background. - JS reads: document.getElementById("rateBYOL").checked - On mobile (≤600px) stacks vertically (grid-template-columns:1fr). - ─────────────────────────────────────────────────────────────── */ - .pill-toggle { - display: grid; - grid-template-columns: 1fr 1fr; - border: 1px solid var(--border); - border-radius: 6px; - overflow: hidden; - margin-bottom: 20px; - } - .pill-toggle input[type=radio] { display: none; } - .pill-toggle label { - padding: 18px 20px; - cursor: pointer; - border-right: 1px solid var(--border); - transition: background 0.15s; - display: flex; - flex-direction: column; - gap: 6px; - } - .pill-toggle label:last-child { border-right: none; } - .pill-toggle input:focus-visible + label { - outline: 2px solid var(--accent); - outline-offset: -2px; - } - .pill-toggle input:checked + label { - background: var(--accent); - color: #fff; - } - .pill-toggle input:checked + label .pill-price { color: #fff; } - .pill-toggle input:checked + label .pill-desc { color: rgba(255,255,255,0.85); } - .pill-toggle label .pill-price { - font-family: 'DM Mono', monospace; - font-size: 20px; - font-weight: 500; - color: var(--ink); - } - .pill-toggle label .pill-price small { font-size: 14px; opacity: 0.6; } - .pill-toggle label .pill-desc { font-size: 14px; opacity: 0.7; } - - /* ── TIER SEGMENT (Section VI — VoIP Basic/Standard/Premium) ─── - 3-column radio toggle. JS activateTier(tier) adds .active class. - .active overrides text colours to white on accent background. - Rates: basic $28 | standard $35 | premium $45 /seat/mo. - ─────────────────────────────────────────────────────────────── */ - .tier-seg-wrap { - display: grid; - grid-template-columns: 1fr 1fr 1fr; - border: 1px solid var(--border); - border-radius: 6px; - overflow: hidden; - margin-bottom: 20px; - } - .tier-seg-wrap input[type=radio] { display: none; } - .tier-seg-wrap input[type=radio]:focus-visible + .tier-seg { - outline: 2px solid var(--accent); - outline-offset: -2px; - } - .tier-seg { - padding: 16px 10px; - cursor: pointer; - border-right: 1px solid var(--border); - text-align: center; - transition: background 0.15s; - } - .tier-seg:last-of-type { border-right: none; } - .tier-seg.active { background: var(--accent); } - .tier-seg .tier-name { - font-family: 'DM Mono', monospace; - font-size: 14px; - text-transform: uppercase; - letter-spacing: 0.07em; - color: var(--muted); - } - .tier-seg.active .tier-name { color: #fff; } - .tier-seg .tier-price { - font-family: 'DM Mono', monospace; - font-size: 22px; - color: var(--ink); - margin-top: 3px; - } - .tier-seg.active .tier-price { color: #fff; } - .tier-seg .tier-sub { font-size: 12px; color: var(--muted); margin-top: 2px; } - .tier-seg.active .tier-sub { color: rgba(255,255,255,0.7); } - - /* ── INNER COLLAPSIBLES (What's Included / Add-Ons) ──────────── - Separate from section-level collapse. JS toggleCollapsible(id) - toggles .open on .collapsible-body and swaps +/- on toggle icon. - .addon-preview-pill pills shown when collapsed (JS toggleCollapsible). - ─────────────────────────────────────────────────────────────── */ - .collapsible-header { - display: flex; - align-items: center; - gap: 8px; - cursor: pointer; - padding: 14px 0; - border-top: 1px solid var(--border); - user-select: none; - } - .collapsible-header--mt16 { margin-top: 16px; } - .collapsible-header--addon { flex-wrap: wrap; gap: 4px; margin-top: 8px; } - .collapsible-toggle { - color: var(--accent); - width: 22px; - flex-shrink: 0; - display: flex; - align-items: center; - transition: transform 0.25s ease; - } - .collapsible-toggle.open { transform: rotate(180deg); } - .collapsible-toggle svg { display: block; } - .collapsible-label { - font-family: 'DM Mono', monospace; - font-size: 14px; - text-transform: uppercase; - letter-spacing: 0.07em; - color: var(--muted); - } - .addon-preview-wrap { - display: flex; flex-wrap: wrap; gap: 5px; - width: 100%; padding-left: 28px; margin-top: 6px; - } - .addon-preview-pill { - font-family: 'DM Mono', monospace; - font-size: 13px; - text-transform: uppercase; - letter-spacing: 0.07em; - color: var(--muted); - border: 1px solid var(--border); - border-radius: 2px; - padding: 3px 8px; - white-space: nowrap; - transition: color 0.15s, border-color 0.15s, background 0.15s; - } - .addon-preview-pill.active { - color: var(--green); - border-color: var(--green); - background: rgba(33,112,69,0.10); - } - .collapsible-body { - padding: 16px 0 20px 28px; - overflow: hidden; - max-height: 0; - opacity: 0; - transition: max-height 0.3s ease, opacity 0.2s ease; - } - .collapsible-body.open { - max-height: 2000px; - opacity: 1; - } - - /* FEATURE LIST */ - .feature-list { - list-style: none; - display: flex; - flex-direction: column; - gap: 10px; - margin-top: 8px; - } - .feature-list li { - font-size: 14px; - color: var(--muted); - line-height: 1.7; - padding-left: 18px; - position: relative; - } - .feature-list li::before { - content: '✓'; - position: absolute; - left: 0; - color: var(--green); - font-size: 11px; - } - .byol-mode .m365-feature { text-decoration: line-through; opacity: 0.55; } - .byol-mode .m365-feature::before { color: var(--amber); } - - /* ── NUMBER INPUTS ────────────────────────────────────────────── - .input-row — flex row: label left, .num-input right - .num-input — DM Mono, text-align:center, oninput→update() - On mobile (≤600px) input-row stacks (flex-direction:column) - and num-input goes full width. - ─────────────────────────────────────────────────────────────── */ - .input-row { - display: flex; - align-items: center; - justify-content: space-between; - padding: 20px 0; - border-top: 1px solid var(--border); - } - .input-label { font-family: 'Lato', sans-serif; font-weight: 700; font-size: 16px; } - .input-sublabel { font-size: 13px; color: var(--muted); margin-top: 5px; line-height: 1.55; } - .num-stepper { - display: flex; - align-items: stretch; - flex-shrink: 0; - } - .step-btn { - background: var(--card); - border: 1px solid var(--border); - color: var(--muted); - font-size: 20px; - font-weight: 400; - width: 36px; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - transition: background 0.12s, color 0.12s; - flex-shrink: 0; - user-select: none; - line-height: 1; - } - .step-btn:first-child { border-radius: 4px 0 0 4px; border-right: none; } - .step-btn:last-child { border-radius: 0 4px 4px 0; border-left: none; } - .step-btn:hover { background: var(--border); color: var(--ink); } - .step-btn:active { background: var(--accent); color: #fff; border-color: var(--accent); } - .num-input { - background: var(--card); - border: 1px solid var(--border); - border-radius: 0; - color: var(--ink); - font-family: 'DM Mono', monospace; - font-size: 22px; - width: 72px; - text-align: center; - padding: 8px; - outline: none; - } - .num-input:focus { border-color: var(--accent); } - .num-input::-webkit-inner-spin-button, - .num-input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; } - .num-input[type=number] { -moz-appearance: textfield; } - - /* ── ADDON ROWS ───────────────────────────────────────────────── - .addon-row — clickable label wrapping a hidden checkbox. - JS toggleAddon(cbId, rowId) toggles .selected class on row. - .selected gets accent-tinted background + border. - Price is right-aligned via margin-left:auto on .addon-price. - ─────────────────────────────────────────────────────────────── */ - .addon-grid { display: flex; flex-direction: column; gap: 4px; } - .addon-row { - display: flex; - align-items: flex-start; - gap: 12px; - padding: 13px 14px; - border-radius: 8px; - cursor: pointer; - border: 1px solid transparent; - transition: background 0.12s, border-color 0.12s; - } - .addon-row:hover { background: var(--card); } - .addon-row input[type=checkbox] { margin-top: 3px; accent-color: var(--accent); flex-shrink: 0; } - .addon-name { font-family: 'Lato', sans-serif; font-weight: 700; font-size: 15px; } - .addon-price { - font-family: 'DM Mono', monospace; - font-size: 14px; - color: var(--accent); - white-space: nowrap; - margin-left: auto; - flex-shrink: 0; - } - .addon-desc { font-size: 13px; color: var(--muted); margin-top: 5px; line-height: 1.6; } - - /* ── BYOL CALLOUTS (Section II) ──────────────────────────────── - Shown/hidden by JS based on BYOL toggle state. - #byolCalloutGreen — M365 savings message (shown when M365 selected) - #byolCalloutRed — missed savings warning (shown when BYOL selected) - display:flex + align-items:flex-start keeps icon pinned to - first line; text wrapped in so it never flows under icon. - ─────────────────────────────────────────────────────────────── */ - .callout-green { - 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; - font-size: 14px; - color: var(--green); - margin-bottom: 24px; - line-height: 1.65; - display: flex; - align-items: flex-start; - gap: 9px; - } - .callout-red { - 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: #e87882; /* slightly lighter than #e06070 for better contrast on dark red bg */ - margin-bottom: 24px; - line-height: 1.65; - display: flex; - align-items: flex-start; - gap: 9px; - } - .hidden { display: none !important; } - - /* ── ADMIN FEE PROGRESS BAR (Section I) ──────────────────────── - Shows progress toward $650 engagement threshold. - JS: progressEl width% = (baseSubtotal / ADMIN_FEE_MINIMUM) * 100 - baseSubtotal = users + endpoints + servers (NOT VoIP or ZT). - Turns green at 100% (threshold met), stays blue below. - ─────────────────────────────────────────────────────────────── */ - .progress-wrap { margin: 16px 0 10px; } - .progress-label { - font-family: 'DM Mono', monospace; - font-size: 12px; - letter-spacing: 0.08em; - text-transform: uppercase; - color: var(--muted); - display: flex; - justify-content: space-between; - margin-bottom: 6px; - } - .progress-track { - height: 7px; - background: var(--border); - border-radius: 4px; - overflow: hidden; - } - .progress-fill { - height: 100%; - border-radius: 3px; - background: var(--accent); - transition: width 0.3s ease, background 0.3s; - } - - /* ── ADMIN FEE BREAKDOWN TABLE (Section I) ───────────────────── - Shows: Base Site Admin | ZT Supplement (if active) | Total. - .fee-total row has top border separator and bold text. - All values rendered by update() via getEl('sl-admin-val') etc. - ─────────────────────────────────────────────────────────────── */ - .fee-table { width: 100%; border-collapse: collapse; margin-top: 16px; font-size: 14px; } - .fee-table td { padding: 8px 0; color: var(--muted); } - .fee-table td:last-child { text-align: right; font-family: 'DM Mono', monospace; color: var(--ink); } - .fee-table tr.fee-total td { border-top: 1px solid var(--border); padding-top: 14px; color: var(--ink); font-weight: 600; } - - /* ── FEATURE CARDS (Section I — What's Covered) ──────────────── - Static content — 8 cards in single-column grid. - Each card has icon (inline SVG) + title (Poppins) + desc (Lato). - Not dynamically rendered; content is hard-coded in HTML. - ─────────────────────────────────────────────────────────────── */ - .feature-card-grid { - display: grid; - grid-template-columns: 1fr; - gap: 10px; - margin-top: 16px; - } - .feature-card { - background: var(--card); - border: 1px solid var(--border); - border-radius: 8px; - padding: 14px 16px; - } - .feature-card-title { font-family: 'Poppins', sans-serif; font-weight: 600; font-size: 14px; margin-bottom: 5px; display:flex; align-items:center; } - .feature-card-desc { font-size: 13px; color: var(--muted); line-height: 1.65; } - - /* ── SIDEBAR (Desktop only, ≤1100px hidden) ───────────────────── - .sidebar-header — accent blue, shows "SVS MSP — LIVE QUOTE" + client name - .sidebar-body — all pricing lines, MRR total, notes, VS comparison, - nudge banner, export button - .sidebar-line — each service line (icon + label + value) - .sidebar-mrr — large Poppins 48px MRR total - IMPORTANT: nudgeBanner MUST live inside .sidebar-body or it will - be clipped when sidebar collapses. Do not add before it. - On mobile: sidebar is hidden; a duplicate (_m IDs) lives inside - .mobile-panel-sheet and is synced by update() via syncEl/syncClass. - ─────────────────────────────────────────────────────────────── */ - .sidebar { - background: var(--card); - border: 1px solid var(--border); - border-radius: 12px; - overflow: hidden; - } - .sidebar-header { - padding: 20px 24px; - background: var(--accent); - } - .sidebar-title { - font-family: 'DM Mono', monospace; - font-size: 12px; - letter-spacing: 0.12em; - text-transform: uppercase; - color: rgba(255,255,255,0.75); - margin-bottom: 4px; - } - .sidebar-client { - font-family: 'Poppins', sans-serif; - font-weight: 600; - font-size: 22px; - color: #fff; - line-height: 1.25; - } - .sidebar-client.placeholder { color: rgba(255,255,255,0.65); font-weight: 400; font-style: italic; } - .sidebar-body { padding: 24px; } - .sidebar-line { - display: flex; - justify-content: space-between; - align-items: baseline; - font-size: 14px; - color: var(--muted); - padding: 8px 0; - border-bottom: 1px solid var(--border); - } - .sidebar-line .val { - font-family: 'DM Mono', monospace; - color: #f2ede4; /* brighter warm white — money figures pop vs labels */ - font-size: 14px; - } - .sidebar-line .lbl-icon { margin-right: 5px; } - .sidebar-mrr-label { - font-family: 'DM Mono', monospace; - font-size: 13px; - letter-spacing: 0.1em; - text-transform: uppercase; - color: var(--muted); - margin-top: 24px; - margin-bottom: 6px; - } - .sidebar-mrr { - font-family: 'Poppins', sans-serif; - font-weight: 700; - font-size: 48px; - color: #f5f0e8; /* brightest text — hero MRR number */ - line-height: 1; - margin-bottom: 16px; - } - .sidebar-note { - font-size: 13px; - color: var(--muted); - line-height: 1.65; - padding: 6px 0; - } - .sidebar-note strong { color: var(--ink); } - - /* ── VS IN-HOUSE COMPARISON ───────────────────────────────────── - Shown only when users > 0 OR endpoints > 0 (JS toggles .hidden). - Compares SVS MRR (annualised) vs 1-person Ottawa IT hire ($85K+tools) - and 5-person team ($420K+tools). Savings rows turn amber if SVS - costs MORE than the comparison (rare at low seat counts). - updateVsComparison(q) renders this section in update(). - ─────────────────────────────────────────────────────────────── */ - .vs-table { width: 100%; border-collapse: collapse; font-size: 13px; } - .vs-table td { padding: 8px 6px; vertical-align: middle; } - .vs-table td:last-child { text-align: right; font-family: 'DM Mono', monospace; white-space: nowrap; } - .vs-table tr:first-child td { padding-bottom: 14px; border-bottom: 1px solid var(--border); } - .vs-table tr:nth-child(2) td, - .vs-table tr:nth-child(4) td { padding-top: 14px; } - .vs-save-row td { padding: 9px 12px; font-size: 12px; font-family: 'DM Mono', monospace; letter-spacing: 0.05em; } - .vs-save-row td:first-child { border-radius: 6px 0 0 6px; } - .vs-save-row td:last-child { border-radius: 0 6px 6px 0; } - .vs-label { - font-family: 'DM Mono', monospace; - font-size: 10px; - letter-spacing: 0.10em; - text-transform: uppercase; - color: var(--muted); - margin-bottom: 10px; - display: flex; - align-items: center; - gap: 8px; - } - .vs-label::after { content: ''; flex: 1; height: 1px; background: var(--border); } - - /* ── INSIGHT NUDGE BANNER ─────────────────────────────────────── - Contextual sales insight shown at bottom of sidebar. - Conditions (evaluated in update() → renderNudge()): - amber — ZT active - green — BYOL selected + users > 0 - green — PWM not selected + users > 0 - Auto-rotates every 30s via startNudgeRotation() (setInterval). - Manual nav via cycleNudge(dir) — does NOT reset the timer. - .nudge-nav-btn — SVG chevron pills (‹ ›), hidden when only 1 nudge. - BOTH #nudgeBanner and #nudgeBanner_m are updated by renderNudge() - via applyNudge('') and applyNudge('_m'). - nudgeBanner sits between .sidebar-header and .sidebar-body. - ─────────────────────────────────────────────────────────────── */ - .nudge-banner { - margin: 0 0 16px 0; - padding: 18px 24px; - font-size: 15px; - line-height: 1.7; - min-height: 130px; - box-sizing: border-box; - } - .nudge-banner.amber { - 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: #162e22; /* match callout-green — was #1a2e20 */ - color: var(--green); /* use token — was off-token #3dc472 */ - border-left: 3px solid var(--green); - } - .nudge-banner-label { - font-family: 'DM Mono', monospace; - font-size: 13px; - text-transform: uppercase; - letter-spacing: 0.1em; - opacity: 1; - display: block; - margin-bottom: 8px; - } - #nudgeCounter { - font-size: 12px; - opacity: 0.55; - } - .nudge-nav-btn { - background: rgba(255,255,255,0.08); - border: none; - cursor: pointer; - padding: 0; - width: 28px; - height: 28px; - border-radius: 5px; - display: flex; - align-items: center; - justify-content: center; - color: inherit; - flex-shrink: 0; - transition: background 0.15s; - } - .nudge-nav-btn:hover { background: rgba(255,255,255,0.15); } - .nudge-nav-btn svg { display: block; } - - /* ── QUOTE SETTINGS BAR ───────────────────────────────────────── - Sits below the client bar, above Section I. - Left: contract term 3-way toggle. - Right: HST checkbox + one-time fee input. - padding-left:96px aligns with section card edges. - ─────────────────────────────────────────────────────────────── */ - - /* ── SECTIONS TOOLBAR (Collapse All / Expand All) ───────────────── */ - .sections-toolbar { - display: flex; - justify-content: flex-end; - margin-left: 96px; - margin-bottom: 10px; - } - .btn-toggle-all { - font-family: 'DM Mono', monospace; - font-size: 11px; - letter-spacing: 0.08em; - text-transform: uppercase; - color: var(--muted); - background: none; - border: 1px solid var(--border); - border-radius: 6px; - padding: 5px 14px; - cursor: pointer; - transition: color 0.15s, border-color 0.15s, background 0.15s; - } - .btn-toggle-all:hover { - color: var(--ink); - border-color: var(--accent); - background: rgba(45, 122, 168, 0.07); - } - - .quote-settings-bar { - margin-left: 96px; - padding: 18px 24px 20px 24px; - display: flex; - align-items: stretch; - gap: 0; - background: var(--card); - border: 1px solid var(--border); - border-radius: 12px; - overflow: hidden; - } - .qs-group { - display: flex; - flex-direction: column; - gap: 8px; - flex: 1; - min-width: 260px; - padding: 0 24px 0 0; - } - .qs-label { - font-family: 'DM Mono', monospace; - font-size: 11px; - letter-spacing: 0.12em; - text-transform: uppercase; - color: var(--muted); - } - .qs-term-wrap { margin-bottom: 0; } - .qs-term-wrap .tier-seg { padding: 10px 8px; } - .qs-term-wrap .tier-name { font-size: 12px; } - .qs-term-wrap .tier-price { display: none; } - - /* Best Value badge on 24-month */ - .qs-best-badge { - display: inline-block; - font-family: 'DM Mono', monospace; - font-size: 9px; - font-weight: 700; - letter-spacing: 0.08em; - text-transform: uppercase; - color: var(--green); - background: rgba(33, 112, 69, 0.13); - border: 1px solid rgba(33, 112, 69, 0.3); - border-radius: 3px; - padding: 1px 5px; - vertical-align: middle; - margin-left: 5px; - line-height: 1.5; - } - .tier-seg.active .qs-best-badge { - color: rgba(255,255,255,0.9); - background: rgba(255,255,255,0.18); - border-color: rgba(255,255,255,0.35); - } - - /* Discount sub-text — green when not active */ - .qs-discount-sub { color: var(--green) !important; } - .tier-seg.active .qs-discount-sub { color: rgba(255,255,255,0.8) !important; } - - /* Dynamic savings row — appears below selector when discounted term active */ - .qs-savings-row { - display: flex; - align-items: center; - gap: 6px; - font-family: 'DM Mono', monospace; - font-size: 11px; - letter-spacing: 0.05em; - color: var(--green); - margin-top: 2px; - } - .qs-savings-row.hidden { display: none; } - #qsSavingsAmt { font-weight: 700; } - - /* Vertical divider between contract term and onboarding fee */ - .qs-divider { - width: 1px; - background: var(--border); - margin: -18px 0 -20px; - flex-shrink: 0; - } - - .qs-right { - display: flex; - flex-direction: column; - gap: 12px; - padding: 0 0 0 24px; - justify-content: center; - } - - /* ── Custom toggle switch (replaces native checkbox for Waive) ── */ - .qs-toggle-row { - display: flex; - align-items: center; - gap: 9px; - cursor: pointer; - user-select: none; - } - .qs-toggle-row input[type=checkbox] { display: none; } - .qs-toggle-row input[type=checkbox]:focus-visible + .qs-switch { - outline: 2px solid var(--accent); - outline-offset: 2px; - } - .qs-switch { - width: 34px; - height: 20px; - background: var(--border); - border-radius: 10px; - position: relative; - transition: background 0.2s; - flex-shrink: 0; - } - .qs-switch::after { - content: ''; - position: absolute; - width: 14px; - height: 14px; - background: #fff; - border-radius: 50%; - top: 3px; - left: 3px; - transition: left 0.2s, background 0.2s; - box-shadow: 0 1px 3px rgba(0,0,0,0.3); - } - .qs-toggle-row input:checked ~ .qs-switch { background: var(--accent); } - .qs-toggle-row input:checked ~ .qs-switch::after { left: 17px; } - .qs-fee-waive:has(input:disabled) { opacity: 0.5; cursor: default; } - .qs-fee-input:disabled { opacity: 0.4; cursor: not-allowed; } - - .qs-toggle-label { - font-family: 'DM Mono', monospace; - font-size: 13px; - color: var(--muted); - letter-spacing: 0.04em; - } - .qs-fee-row { - display: flex; - flex-direction: column; - gap: 6px; - } - .qs-fee-header { - display: flex; - align-items: center; - gap: 10px; - } - .qs-fee-waive { margin-left: 4px; } - .qs-fee-label { - font-family: 'DM Mono', monospace; - font-size: 13px; - color: var(--muted); - white-space: nowrap; - letter-spacing: 0.04em; - } - .qs-fee-input-wrap { - display: flex; - align-items: center; - background: var(--card); - border: 1px solid var(--border); - border-radius: 4px; - overflow: hidden; - } - .qs-fee-dollar { - padding: 6px 8px; - font-family: 'DM Mono', monospace; - font-size: 14px; - color: var(--muted); - background: var(--card); - border-right: 1px solid var(--border); - } - .qs-fee-input { - background: var(--card); - border: none; - color: var(--ink); - font-family: 'DM Mono', monospace; - font-size: 14px; - width: 120px; - text-align: center; - padding: 6px 10px; - outline: none; - } - .qs-fee-input::-webkit-inner-spin-button, - .qs-fee-input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; } - .qs-fee-input[type=number] { -moz-appearance: textfield; } - - /* ── INLINE-STYLE REPLACEMENT CLASSES ─────────────────────────── - These replace presentational style="" attributes that previously - bypassed the design token system. All colours use tokens. - ─────────────────────────────────────────────────────────────── */ - - /* Section I — admin fee display row */ - /* .admin-fee-header base styles merged into the waived section definition at line ~1079 */ - .admin-fee-title { font-family: 'Poppins', sans-serif; font-weight: 600; font-size: 22px; } - .admin-fee-val { font-family: 'DM Mono', monospace; font-size: 22px; color: var(--accent); } - .admin-fee-sub { font-size: 12px; color: var(--muted); margin-bottom: 12px; } - .floor-note { font-size: 13px; color: var(--muted); margin-top: 8px; margin-bottom: 16px; font-family: 'DM Mono', monospace; } - - /* Sidebar sub-line rows (users/endpoints/admin breakdown text) */ - .sl-sub { font-size: 13px; color: var(--muted); font-family: 'DM Mono', monospace; padding: 0 0 6px; } - - /* Per-user cost section */ - .per-user-cost-sub { font-size: 10px; opacity: 0.6; font-weight: 400; } - .sidebar-note-mono { font-size: 12px; padding: 2px 0 6px; font-family: 'DM Mono', monospace; } - - /* VS Comparison block */ - .vs-comparison-wrap { - margin-top: 16px; - margin-bottom: 15px; - padding: 24px 24px 22px; - background: rgba(255, 255, 255, 0.06); - border: 1px solid var(--border); - border-radius: 10px; - } - .vs-inline-icon { margin-right: 6px; vertical-align: middle; } - .vs-svs-label { font-size: 14px; color: #f2ede4; font-weight: 600; } - .vs-val-accent { color: #5aaedc; font-weight: 600; font-size: 14px; } - .vs-td-muted { color: #b5ab9e; font-size: 13px; } - .vs-td-icon { margin-right: 5px; opacity: 0.7; vertical-align: middle; } - .vs-footnote { - font-size: 11px; - color: var(--muted); - margin-top: 10px; - padding-top: 10px; - border-top: 1px solid var(--border); - line-height: 1.55; - font-style: italic; - } - - /* Side note icons and savings highlight */ - .note-icon { margin-right: 6px; vertical-align: middle; flex-shrink: 0; } - .savings-amount { color: var(--green); } - .sl-otf-waived > span:first-child { color: var(--green); text-decoration: line-through; text-decoration-color: var(--green); } - .sl-otf-waived .val { color: var(--green); font-size: 12px; letter-spacing: 0.04em; } - .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; margin-bottom: 6px; } - .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; } - - /* VoIP savings prompt */ - .savings-prompt { font-size: 13px; color: var(--muted); margin-top: 8px; } - - /* ── SIDEBAR UTILITY CLASSES ───────────────────────────────────── - .sl-muted — de-emphasised row labels/values - .sl-discount-val — green discount amount - .sl-hst-val — muted HST amount - ─────────────────────────────────────────────────────────────── */ - .sl-muted { color: var(--muted) !important; font-size: 13px; } - .sl-discount-val { color: var(--green) !important; font-size: 13px; } - .sl-hst-val { color: var(--muted) !important; font-size: 13px; } - .sidebar-line-discount { border-bottom-style: dashed; opacity: 0.8; } - .sidebar-line-hst { border-color: transparent; padding-top: 4px; padding-bottom: 4px; } - .sidebar-line-total { font-weight: 600; border-top: 1px solid var(--border); margin-top: 4px; padding-top: 10px; } - .sl-hst-toggle { - display: flex; align-items: center; gap: 6px; - font-size: 12px; color: var(--muted); - font-family: 'DM Mono', monospace; letter-spacing: 0.04em; - cursor: pointer; user-select: none; - margin: 6px 0 4px; - } - .sl-hst-toggle input { accent-color: var(--accent); cursor: pointer; } - - /* ── VS COMPARISON CSS CLASSES (replace inline styles) ────────── - .vs-save-green — green "YOU SAVE" row background - .vs-save-amber — amber "Costs more" row background - .vs-val-green — green text for savings value/label - .vs-val-amber — amber text for "costs more" value/label - ─────────────────────────────────────────────────────────────── */ - .vs-save-green td { background: rgba(39, 174, 96, 0.16); } - .vs-save-amber td { background: rgba(210, 120, 30, 0.16); } - .vs-val-green { color: var(--green) !important; } - .vs-val-amber { color: var(--amber) !important; } - - /* ── SECTION CARD HOVER / OPEN POLISH ─────────────────────────── - Subtle left accent glow on hover; stronger treatment when open. - ─────────────────────────────────────────────────────────────── */ - .section { - transition: border-color 0.2s, box-shadow 0.2s; - } - .section:hover { - border-color: rgba(45,122,168,0.35); - box-shadow: -3px 0 0 0 rgba(45,122,168,0.4); - } - .sec-open { - border-color: rgba(45,122,168,0.5) !important; - box-shadow: -3px 0 0 0 rgba(45,122,168,0.7) !important; - } - - /* ── ADDON ROW SELECTED — stronger check indicator ────────────── - .selected gets a more prominent border + check indicator via - the checkbox's native accent-color. No pseudo-element needed. - ─────────────────────────────────────────────────────────────── */ - .addon-row.selected { - background: #1d2d3a; - border-color: var(--accent); - box-shadow: inset 3px 0 0 0 var(--accent); - } - .addon-row.selected .addon-name { color: var(--ink); } - .addon-row.selected .addon-price { color: #62c5f0; } - - /* ── EXPORT BUTTONS ───────────────────────────────────────────── - Primary CTA: Print / Save PDF - Secondary: Export JSON + Copy - ─────────────────────────────────────────────────────────────── */ - .export-wrap { - padding: 20px 24px 24px; - background: var(--card); - display: flex; - flex-direction: column; - gap: 8px; - } - .btn-export { - width: 100%; - background: var(--accent); - color: #fff; - border: none; - border-radius: 6px; - padding: 15px 16px; - font-family: 'DM Mono', monospace; - font-size: 14px; - letter-spacing: 0.07em; - text-transform: uppercase; - cursor: pointer; - transition: background 0.15s, transform 0.1s; - display: flex; - align-items: center; - justify-content: center; - } - .btn-export:hover { background: #3a8fc4; } - .btn-export:active { transform: scale(0.98); } - .btn-export-secondary { - background: transparent; - border: 1px solid var(--border); - color: var(--muted); - font-size: 13px; - padding: 11px 16px; - } - .btn-export-secondary:hover { background: var(--card); border-color: var(--accent); color: var(--ink); } - - /* ── VOIP PHONE BILL SAVINGS ESTIMATOR (Section VI) ──────────── - Optional input: current monthly phone bill. - updateSavings(q) compares against voipTotal and shows green - savings message or amber warning if VoIP costs more. - On mobile stacks vertically (flex-direction:column). - ─────────────────────────────────────────────────────────────── */ - .savings-input-row { - display: flex; - align-items: center; - gap: 12px; - margin-top: 16px; - padding-top: 16px; - border-top: 1px solid var(--border); - } - .savings-input-row label { - font-size: 14px; - color: var(--muted); - flex: 1; - } - .savings-input-row input { - background: var(--card); - border: 1px solid var(--border); - border-radius: 4px; - color: var(--ink); - font-family: 'DM Mono', monospace; - font-size: 18px; - width: 120px; - text-align: center; - padding: 7px; - outline: none; - } - .savings-result { - margin-top: 12px; - background: #162e22; /* match callout-green — was #0d2016 (near-black) */ - border: 1px solid #245840; - border-radius: 6px; - padding: 12px 16px; - font-family: 'DM Mono', monospace; - font-size: 14px; - color: var(--green); - line-height: 1.65; - } - /* Amber modifier — toggled by JS (classList.add/remove) when VoIP quote > current bill */ - .savings-result.savings-amber { - background: #2e1f08; - border-color: #5a3a10; - color: var(--amber); - } - - /* ── BOTTOM PITCH BANNER ──────────────────────────────────────── - 4-column grid (2-col on tablet/mobile) outside the .outer grid. - .pitch-inner has margin-left:96px to align with section cards. - Columns: Security-First | Ottawa-Based | Flat-Rate | Scales With You - .pitch-footer — green strip at bottom with tagline. - Icons are inline SVG (FA Free 6.5.0 paths), accent blue. - ─────────────────────────────────────────────────────────────── */ - .pitch-wrap { - width: 100%; - padding: 0; - margin: 0; - } - .pitch-inner { - margin-left: 0; - background: var(--card); - border: none; - border-top: 1px solid var(--border); - border-radius: 0; - overflow: hidden; - } - .pitch-grid { - display: grid; - grid-template-columns: repeat(4, 1fr); - } - .pitch-item { - padding: 30px 24px; - border-right: 1px solid var(--border); - } - .pitch-item:last-child { border-right: none; } - .pitch-head { - display: flex; - align-items: center; - gap: 12px; - margin-bottom: 10px; - min-height: 28px; - } - .pitch-icon { - display: inline-flex; - align-items: center; - justify-content: center; - flex: 0 0 auto; - font-size: 20px; - color: var(--accent); - } - .pitch-title { - font-family: 'Poppins', sans-serif; - font-weight: 600; - font-size: 16px; - line-height: 1.3; - margin: 0; - } - .pitch-desc { font-size: 14px; color: var(--muted); line-height: 1.7; } - .pitch-footer { - background: #162e22; /* match green callout family — was #1a2e20 */ - border-top: 1px solid #245840; - padding: 16px 32px; - font-family: 'DM Mono', monospace; - font-size: 13px; - color: var(--green); - letter-spacing: 0.05em; - text-align: center; - } - - /* ═══════════════════════════════════════════════════════ - RESPONSIVE BREAKPOINTS — MOBILE FIRST - ───────────────────────────────────────────────────── - ≤1100px tablet portrait — single col, sidebar hidden, - mobile pill + panel shown - ≤ 900px small tablet — tighter spacing, smaller numerals - ≤ 600px phone portrait — no numeral gutter, section-num - inline, section-header grid layout - ≤ 780px landscape — restore 2-col, sticky sidebar - ───────────────────────────────────────────────────── - MOBILE PANEL ARCHITECTURE: - Desktop — .side-col visible, .mobile-quote-panel hidden - ≤1100px — .side-col hidden (display:none), pill shown - Pill tap — openMobilePanel() adds .open to #mobileQuotePanel - Panel contains static duplicate sidebar with _m ID suffix - update() syncs all _m elements via syncEl/syncClass/syncStyle - DO NOT add display:none to .side-col at desktop level or the - sidebar will disappear on desktop after panel is opened. - ═══════════════════════════════════════════════════════ */ - /* ═══════════════════════════════════════════════════════ - RESPONSIVE — MOBILE FIRST - Breakpoints: - < 600px — phone portrait - 600–900px — phone landscape / small tablet - 900–1100px — tablet portrait - 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: var(--sidebar-top-gap) 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 { - grid-template-columns: 1fr; - gap: 0; - padding: 36px clamp(16px,3vw,32px) 60px; - } - .side-col { - position: static; - margin-top: 0; - } - .sidebar { - margin-top: 0; - border-radius: 12px; - } - /* Sidebar sits ABOVE the form on tablet/mobile */ - .main-col { order: 2; } - .side-col { order: 1; } - - /* Narrower numeral gutter */ - .section { margin-left: 64px; } - .section-num { left: -64px; width: 56px; font-size: 52px; } - .client-bar { padding: 24px 0 24px 64px; } - .quote-settings-bar { margin-left: 64px; padding: 18px 22px 20px 22px; gap: 0; } - .qs-group { padding-right: 20px; } - .qs-right { padding-left: 20px; } - .sections-toolbar { margin-left: 64px; } - .top-bar-logo { margin-left: 38px; } - .pitch-inner { margin-left: 0; } - - .pitch-grid { grid-template-columns: repeat(2, 1fr); } - .pitch-item:nth-child(2) { border-right: none; } - .pitch-item:nth-child(3) { border-top: 1px solid var(--border); } - .pitch-item:nth-child(4) { border-top: 1px solid var(--border); border-right: none; } - - /* Addon rows — price above title so text has full width */ - .addon-row { - display: grid; - grid-template-columns: auto 1fr; - grid-template-rows: auto auto; - column-gap: 10px; - row-gap: 6px; - padding: 12px 14px; - align-items: start; - } - .addon-row input[type=checkbox] { grid-column: 1; grid-row: 2; } - .addon-row > div { grid-column: 2; grid-row: 2; } - .addon-price { - grid-column: 1 / -1; - grid-row: 1; - margin-left: 0; - } - } - - /* ── SMALL TABLET / LANDSCAPE PHONE (≤ 900px) ── */ - @media (max-width: 900px) { - .top-bar { padding: 12px 0; } - .outer { padding: 28px clamp(14px,3vw,28px) 48px; } - - .section { margin-left: 52px; padding: 24px 24px 28px; } - .section-num { left: -52px; width: 44px; font-size: 42px; top: 24px; } - .top-bar-logo { margin-left: 26px; } - .client-bar { padding: 20px 0 20px 52px; } - .quote-settings-bar { margin-left: 52px; padding: 16px 18px; gap: 0; } - .qs-group { padding-right: 16px; } - .qs-right { padding-left: 16px; } - .sections-toolbar { margin-left: 52px; } - .pitch-wrap { padding: 0; } - .pitch-inner { margin-left: 0; } - - .section-header { - flex-wrap: wrap; - align-items: center; - gap: 8px 12px; - margin-bottom: 24px; - } - .section-title-block { order: 2; flex: 0 0 100%; } - .sec-summary-badge { order: 1; } - .sec-chevron { order: 1; margin-left: auto; } - .section-title { font-size: 20px; } - - .main-col { gap: 20px; } - .main-col > .section:first-of-type { margin-top: 16px; } - } - - /* ── PHONE (≤ 600px) ── */ - @media (max-width: 600px) { - /* No gutter — numerals tuck inline */ - .outer { padding: 20px 16px 40px; } - - /* Collapse numeral gutter entirely on phones */ - .top-bar-logo { margin-left: 0; } - .section { - margin-left: 0; - padding: 20px 18px 24px; - border-radius: 10px; - } - .section-num { - position: static; - display: inline-block; - font-size: 20px; - width: auto; - color: var(--accent); - background: transparent; - border: none; - border-radius: 0; - padding: 0; - margin-bottom: 8px; - letter-spacing: 0.06em; - line-height: 1; - text-align: left; - font-family: 'Cinzel', serif; - opacity: 0.85; - } - /* ── Mobile section header: top row = numeral + right-side controls - bottom row = title block full width ── */ - .section-header { - display: grid; - /* Col 1: numeral (auto width) | Col 2: badge+chevron (auto) */ - grid-template-columns: auto 1fr auto; - grid-template-rows: auto auto; - column-gap: 10px; - row-gap: 8px; - margin-bottom: 20px; - align-items: center; - } - /* Numeral: top-left */ - .section-num { - grid-column: 1; - grid-row: 1; - } - /* Summary badge: top-middle (expands to fill) — right-aligned */ - .sec-summary-badge { - grid-column: 2; - grid-row: 1; - text-align: right; - justify-self: end; - white-space: nowrap; - font-size: 12px; - margin-left: 0; - order: 0; - } - /* Chevron: top-right with pill background */ - .sec-chevron { - grid-column: 3; - grid-row: 1; - padding: 0; - width: 36px; - height: 36px; - display: flex !important; - align-items: center; - justify-content: center; - background: rgba(255,255,255,0.07); - border-radius: 6px; - color: var(--muted); - flex-shrink: 0; - } - .sec-chevron svg { width: 16px; height: 16px; stroke-width: 3; } - /* Title block: second row, full width */ - .section-title-block { - grid-column: 1 / -1; - grid-row: 2; - width: 100%; - min-width: 0; - order: 0; - flex: initial; - } - .section-title { font-size: 18px; } - - .client-bar { padding: 20px 0 20px 0; } - .client-input { font-size: 22px; max-width: 100%; } - .quote-settings-bar { margin-left: 0; padding: 14px 16px 16px; flex-direction: column; gap: 0; } - .sections-toolbar { margin-left: 0; } - .qs-group { min-width: 0; padding-right: 0; } - /* Convert vertical divider to horizontal rule */ - .qs-divider { width: auto; height: 1px; margin: 14px 0; } - .qs-right { padding-left: 0; } - - .main-col { gap: 16px; } - .main-col > .section:first-of-type { margin-top: 8px; } - - /* Pill toggle — stack vertically on tiny screens */ - .pill-toggle { - grid-template-columns: 1fr; - } - .pill-toggle label { border-right: none; border-bottom: 1px solid var(--border); } - .pill-toggle label:last-child { border-bottom: none; } - - /* Tier segments — keep 3-col but tighter */ - .tier-seg { padding: 12px 6px; } - .tier-seg .tier-price { font-size: 18px; } - .tier-seg .tier-name { font-size: 11px; } - - /* Input rows — stack label above input */ - .input-row { - flex-direction: column; - align-items: flex-start; - gap: 12px; - } - .num-stepper { width: 100%; } - .num-input { width: 100%; font-size: 20px; padding: 12px; flex: 1; } - .step-btn { width: 48px; font-size: 22px; } - - /* Addon rows — tighter font on phones (grid inherited from ≤1100px) */ - .addon-row { padding: 12px 10px; } - .addon-price { font-size: 13px; } - .addon-name { font-size: 14px; } - .addon-desc { font-size: 12px; } - - /* Collapsible */ - .collapsible-body { padding: 12px 0 16px 16px; } - - /* Feature cards — single col already, just tighter */ - .feature-card { padding: 12px 14px; } - - /* Savings row — stack */ - .savings-input-row { flex-direction: column; align-items: flex-start; gap: 8px; } - .savings-input-row input { width: 100%; } - - /* Sidebar */ - .sidebar-body { padding: 16px; } - .sidebar-header { padding: 16px 18px; } - .sidebar-mrr { font-size: 38px; } - .sidebar-client { font-size: 18px; } - - /* VS table — tighten */ - .vs-table td { padding: 5px 3px; font-size: 13px; } - - /* Pitch footer */ - .pitch-wrap { padding: 0; } - .pitch-inner { margin-left: 0; border-radius: 0; } - .pitch-grid { grid-template-columns: 1fr 1fr; } - .pitch-item { padding: 20px 16px; } - .pitch-item:nth-child(2) { border-right: none; } - .pitch-item:nth-child(3) { border-top: 1px solid var(--border); } - .pitch-item:nth-child(4) { border-top: 1px solid var(--border); border-right: none; } - .pitch-title { font-size: 14px; } - .pitch-desc { font-size: 13px; } - .pitch-footer { padding: 14px 16px; font-size: 12px; } - - /* Nudge banner */ - .nudge-banner { padding: 14px 16px; font-size: 14px; } - .export-wrap { padding: 16px 16px 20px; } - .confirm-modal-card { - margin-top: 8vh; - padding: 20px 18px 18px; - } - .confirm-modal-title { font-size: 21px; } - .confirm-modal-actions { flex-direction: column-reverse; } - .confirm-btn { width: 100%; } - - /* Fee table */ - .fee-table td { padding: 7px 0; font-size: 13px; } - } - - /* ── LANDSCAPE PHONE (≤ 780px, orientation: landscape) ── */ - @media (max-width: 780px) and (orientation: landscape) { - .outer { - grid-template-columns: 1fr 1fr; - gap: 24px; - padding: 20px 20px 40px; - align-items: start; - } - .main-col { order: 1; gap: 16px; } - .side-col { - order: 2; - position: sticky; - top: 60px; - align-self: start; - } - .section { margin-left: 44px; padding: 18px 20px 22px; } - .section-num { left: -44px; width: 38px; font-size: 36px; top: 18px; position: absolute; } - .client-bar { padding: 16px 0 16px 44px; } - .sidebar { margin-top: 0; } - .sidebar-mrr { font-size: 32px; } - .pitch-grid { grid-template-columns: repeat(2, 1fr); } - .pitch-inner { margin-left: 0; } - .pitch-wrap { padding: 0; } - } - - - /* ── MOBILE-ONLY ELEMENTS — hidden at desktop baseline ───────── - MUST be display:none here (outside any media query) so that - the panel doesn't render on top of desktop layout. - The @media (max-width:1100px) block below overrides to display:flex. - ─────────────────────────────────────────────────────────────── */ - .mobile-quote-pill { display: none; } - .mobile-quote-panel { display: none; } - .mobile-panel-actions { display: none; } - - /* ═══════════════════════════════════════ - MOBILE QUOTE PILL + FULL-SCREEN PANEL - ═══════════════════════════════════════ */ - - - @media (max-width: 1100px) { - /* Hide the static sidebar entirely on mobile/tablet */ - .side-col { display: none; } - - /* Show the floating pill */ - .mobile-quote-pill { - display: flex; - align-items: center; - gap: 10px; - position: fixed; - top: 82px; - right: 14px; - z-index: 200; - background: var(--accent); - color: #fff; - border-radius: 50px; - padding: 10px 18px 10px 14px; - cursor: pointer; - box-shadow: 0 4px 20px rgba(0,0,0,0.45); - border: none; - font-family: 'DM Mono', monospace; - font-size: 15px; - font-weight: 500; - letter-spacing: 0.04em; - transition: background 0.15s, transform 0.15s; - user-select: none; - -webkit-tap-highlight-color: transparent; - } - .mobile-quote-pill:active { transform: scale(0.96); } - .mobile-quote-pill:hover { background: #3a8fc4; } - .mobile-pill-icon { - width: 28px; - height: 28px; - background: rgba(255,255,255,0.2); - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - } - .mobile-pill-mrr { - font-family: 'DM Mono', monospace; - font-size: 16px; - font-weight: 500; - line-height: 1; - } - .mobile-pill-label { - font-size: 10px; - opacity: 0.75; - letter-spacing: 0.1em; - text-transform: uppercase; - line-height: 1; - margin-top: 2px; - } - - /* Full-screen overlay panel */ - .mobile-quote-panel { - position: fixed; - inset: 0; - z-index: 300; - display: flex; - flex-direction: column; - pointer-events: none; - opacity: 0; - transition: opacity 0.25s ease; - } - .mobile-quote-panel.open { - pointer-events: all; - opacity: 1; - } - - /* Dark backdrop */ - .mobile-panel-backdrop { - position: absolute; - inset: 0; - background: rgba(0,0,0,0.65); - backdrop-filter: blur(3px); - -webkit-backdrop-filter: blur(3px); - } - - /* Slide-up sheet */ - .mobile-panel-sheet { - position: absolute; - bottom: 0; - left: 0; - right: 0; - max-height: 100vh; - background: var(--card); - border-radius: 0; - overflow-y: auto; - overscroll-behavior: contain; - -webkit-overflow-scrolling: touch; - transform: translateY(100%); - transition: transform 0.3s cubic-bezier(0.32, 0.72, 0, 1); - will-change: transform; - border-top: 1px solid var(--border); - } - .mobile-quote-panel.open .mobile-panel-sheet { - transform: translateY(0); - } - - /* Drag handle */ - .mobile-panel-handle { - width: 40px; - height: 4px; - background: var(--border); - border-radius: 2px; - margin: 14px auto 0; - flex-shrink: 0; - } - - /* Close button row */ - .mobile-panel-close-row { - display: flex; - align-items: center; - justify-content: space-between; - padding: 16px 20px 12px; - border-bottom: 1px solid var(--border); - } - .mobile-panel-actions { - display: block; - padding: 0 20px 12px; - border-bottom: 1px solid var(--border); - background: var(--card); - } - .mobile-panel-actions .btn-reset-quote { - margin-top: 12px; - } - .mobile-panel-close-title { - font-family: 'DM Mono', monospace; - font-size: 12px; - text-transform: uppercase; - letter-spacing: 0.12em; - color: var(--muted); - } - .mobile-panel-close-btn { - background: var(--border); - border: none; - color: var(--ink); - border-radius: 50%; - width: 36px; - height: 36px; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - font-size: 20px; - line-height: 1; - flex-shrink: 0; - -webkit-tap-highlight-color: transparent; - transition: background 0.15s; - } - .mobile-panel-close-btn:active { background: var(--muted); } - - /* Sidebar inside the mobile sheet — strip all desktop positioning */ - .mobile-panel-sheet .sidebar { - margin-top: 0 !important; - border-radius: 0 !important; - border: none !important; - box-shadow: none !important; - overflow: visible !important; - } - /* Keep Live Quote header visible in responsive panel so - Insight can sit directly below it (matching desktop order). */ - .mobile-panel-sheet .sidebar-header { - display: block !important; - } - .mobile-panel-sheet .sidebar-body { - padding-top: 0 !important; - } - .mobile-panel-sheet .nudge-banner { - margin-bottom: 35px; - } - } - - /* Landscape phone — pill stays, sheet max-height smaller */ - @media (max-width: 780px) and (orientation: landscape) { - .mobile-panel-sheet { max-height: 88vh; } - } - - /* ═══════════════════════════════════════════════════════ - PRINT / PDF EXPORT (Export A) - window.print() triggers this via Print / Save PDF button. - Goals: - - Clean, branded quote document - - Hide all interactive controls - - Force all sections expanded (body shown) - - No background colours that waste ink (except header) - - Page-break control so summary never splits - ═══════════════════════════════════════════════════════ */ - @media print { - /* ── Force light background on body ── */ - body { background: #fff !important; color: #1a1a1a !important; font-size: 13px; } - - /* ── Hide interactive & mobile-only elements ── */ - .mobile-quote-pill, - .mobile-quote-panel, - .step-btn, - .collapsible-header, - .sec-chevron, - .section-toggle, - .tier-seg-wrap, - .pill-toggle, - .addon-row input[type=checkbox], - .savings-input-row, - .export-wrap, - .nudge-banner, - .pitch-wrap, - .quote-settings-bar, - .section-header.section-toggle { pointer-events: none; } - - .mobile-quote-pill { display: none !important; } - .mobile-quote-panel { display: none !important; } - .export-wrap { display: none !important; } - .nudge-banner { display: none !important; } - .theme-toggle-btn { display: none !important; } - .pitch-wrap { display: none !important; } - .step-btn { display: none !important; } - .collapsible-header { display: none !important; } - .sec-chevron { display: none !important; } - .sec-summary-badge { display: none !important; } - .sec-collapsed-counter { display: none !important; } - .quote-settings-bar { display: none !important; } - .section-badge { display: none !important; } - #savingsPrompt { display: none !important; } - - /* ── Show ALL section bodies (force expand) ── */ - .section-body { display: block !important; } - .collapsible-body { max-height: none !important; opacity: 1 !important; overflow: visible !important; } - - /* ── Reset layout to single column ── */ - .outer { - display: block !important; - padding: 0 !important; - max-width: 100% !important; - } - .main-col, .side-col { width: 100% !important; position: static !important; } - - /* ── Top bar: keep accent, reduce height ── */ - .top-bar { - position: static !important; - padding: 10px 20px !important; - border-bottom: 2px solid #2d7aa8 !important; - background: #fff !important; - } - .top-bar-inner { padding: 0 !important; } - .top-bar-right { color: #555 !important; } - - /* ── Section cards: clean borders, no dark bg ── */ - .section { - background: #fff !important; - border: 1px solid #ccc !important; - box-shadow: none !important; - margin-left: 0 !important; - page-break-inside: avoid; - break-inside: avoid; - padding: 16px 20px !important; - margin-bottom: 12px !important; - } - .section-num { color: #bbb !important; } - .section-title { font-size: 16px !important; } - - /* ── Sidebar: show inline after sections, styled for print ── */ - .sidebar { - background: #fff !important; - border: 2px solid #2d7aa8 !important; - border-radius: 6px !important; - margin: 16px 0 !important; - page-break-inside: avoid; - break-inside: avoid; - } - .sidebar-header { background: #2d7aa8 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; } - .sidebar-mrr { font-size: 36px !important; color: #1a1a1a !important; } - .sidebar-line { color: #444 !important; border-bottom-color: #ddd !important; } - .sidebar-line .val { color: #1a1a1a !important; } - - /* ── VS comparison: clean for print ── */ - .vs-save-green td { background: #e8f5e9 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; } - .vs-save-amber td { background: #fff3e0 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; } - .vs-save-amber { background: #fff8e1 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; } - - /* ── Feature cards: minimal ── */ - .feature-card { background: #f9f9f9 !important; border-color: #ddd !important; } - .feature-card-grid { grid-template-columns: 1fr 1fr !important; gap: 6px !important; } - - /* ── Addon rows ── */ - .addon-row { border-color: #ddd !important; } - .addon-row.selected { background: #e8f4fb !important; border-color: #2d7aa8 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; } - - /* ── Callout boxes ── */ - .callout-green { background: #f0faf4 !important; border-color: #3ab870 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; } - .callout-red { background: #fff0f0 !important; border-color: #c4526a !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; } - - /* ── Progress bar ── */ - .progress-fill { -webkit-print-color-adjust: exact; print-color-adjust: exact; } - - /* ── Print footer ── */ - .pitch-footer { display: none !important; } - - /* ── Page break: force summary sidebar to start fresh ── */ - .side-col { page-break-before: always; break-before: always; } - - /* ── Input fields: show values as static text ── */ - .num-input, .qs-fee-input { - border: none !important; - background: transparent !important; - font-weight: 700 !important; - } - .client-input { - border: none !important; - background: transparent !important; - } - - /* ── Print footer note ── */ - body::after { - content: 'Prepared by Silicon Valley Services (SVS) MSP · Ottawa, Ontario · This quote is valid for 30 days from date of issue. Questions? Contact your SVS account representative.'; - display: block; - font-size: 11px; - color: #888; - border-top: 1px solid #ddd; - padding-top: 10px; - margin-top: 20px; - font-family: 'DM Mono', monospace; - } - } +/* SVS MSP Calculator - Base Manifest */ +/* Phase 5 keeps the original filename stable for the HTML shell while the + actual styles are split into concern-specific files behind it. */ + +@import url('SVS-MSP-Calculator-tokens.css'); +@import url('SVS-MSP-Calculator-base.css'); +@import url('SVS-MSP-Calculator-layout.css'); +@import url('SVS-MSP-Calculator-components.css'); +@import url('SVS-MSP-Calculator-responsive.css'); +@import url('SVS-MSP-Calculator-print.css'); diff --git a/SVS-MSP-Calculator.html b/SVS-MSP-Calculator.html index f78af05..226d370 100644 --- a/SVS-MSP-Calculator.html +++ b/SVS-MSP-Calculator.html @@ -17,12 +17,10 @@ Shows live MRR from #mrrDisplay via update() wrapper. Click → openMobilePanel() ════════════════════════════════════════════════════════════ --> -
- + +
@@ -78,7 +83,7 @@ @@ -92,6 +97,18 @@
Prepared for
+
+
Prepared by
+ +
+
+ +
+
-
Contract Term
+
+
Contract Term & Incentives
+
-
- - +
$
+
-
- -
- -
-
-
I
+
+ -
+ +
+
+ Managed Service Threshold +
+
+
+
+
+
+