2025-08-01 11:51:29 -06:00

2125 lines
63 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Changemaker Lite - Campaign Power Tools</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--primary: #6f42c1;
--primary-dark: #5a32a3;
--accent: #F5A9B8;
--text-dark: #1a1a1a;
--text-light: #666;
--bg-light: #f8f9fa;
--bg-white: #ffffff;
--border: #e0e0e0;
--success: #28a745;
--warning: #ffc107;
--shadow: 0 2px 4px rgba(0,0,0,0.1);
--shadow-lg: 0 10px 30px rgba(0,0,0,0.1);
}
body.dark {
--primary: #8B5CF6; /* A slightly brighter purple for dark mode */
--primary-dark: #7C3AED;
--accent: #EC4899; /* A brighter pink */
--text-dark: #E2E8F0; /* slate-200 */
--text-light: #94A3B8; /* slate-400 */
--bg-light: #1E293B; /* slate-800 */
--bg-white: #0F172A; /* slate-900 */
--border: #334155; /* slate-700 */
--success: #4ADE80; /* green-400 */
--warning: #FBBF24; /* amber-400 */
--shadow: 0 2px 4px rgba(0,0,0,0.2);
--shadow-lg: 0 10px 30px rgba(0,0,0,0.2);
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
color: var(--text-dark);
line-height: 1.6;
overflow-x: hidden;
background-color: var(--bg-white);
transition: background-color 0.3s ease;
}
/* Header */
.header {
position: fixed;
top: 0;
width: 100%;
background: var(--bg-white);
box-shadow: var(--shadow);
z-index: 1000;
transition: all 0.3s ease;
}
.header.scrolled {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
}
body.dark .header.scrolled {
background: rgba(15, 23, 42, 0.85); /* slate-900 with transparency */
}
.nav-container {
max-width: 1200px;
margin: 0 auto;
padding: 1rem 2rem;
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
font-size: 1.5rem;
font-weight: 700;
color: var(--primary);
}
.nav-items {
display: flex;
align-items: center;
gap: 2rem;
}
.nav-links {
display: flex;
gap: 2rem;
list-style: none;
}
.nav-links a {
text-decoration: none;
color: var(--text-dark);
font-weight: 500;
transition: color 0.3s ease;
}
.nav-links a:hover {
color: var(--primary);
}
.cta-button {
background: var(--primary);
color: white;
padding: 0.75rem 1.5rem;
border-radius: 8px;
text-decoration: none;
font-weight: 600;
transition: all 0.3s ease;
}
.cta-button:hover {
background: var(--primary-dark);
transform: translateY(-2px);
box-shadow: var(--shadow-lg);
}
/* Theme Toggle */
.theme-switch-wrapper {
display: flex;
align-items: center;
}
.theme-switch {
display: inline-block;
height: 24px;
position: relative;
width: 48px;
}
.theme-switch input {
display:none;
}
.slider {
background-color: #ccc;
bottom: 0;
cursor: pointer;
left: 0;
position: absolute;
right: 0;
top: 0;
transition: .4s;
border-radius: 24px;
}
.slider:before {
background-color: #fff;
bottom: 4px;
content: "";
height: 16px;
left: 4px;
position: absolute;
transition: .4s;
width: 16px;
border-radius: 50%;
}
input:checked + .slider {
background-color: var(--primary);
}
input:checked + .slider:before {
transform: translateX(24px);
}
/* Hero Section */
.hero {
padding: 8rem 2rem 4rem;
background: linear-gradient(135deg, var(--bg-light) 0%, var(--bg-white) 100%);
text-align: center;
}
.hero-content {
max-width: 800px;
margin: 0 auto;
}
.hero-badge {
display: inline-block;
background: var(--accent);
color: var(--text-dark);
padding: 0.5rem 1rem;
border-radius: 20px;
font-size: 0.875rem;
font-weight: 600;
margin-bottom: 1rem;
}
.canadian-badge {
display: inline-block;
background: #ff0000;
color: white;
padding: 0.5rem 1rem;
border-radius: 20px;
font-size: 0.875rem;
font-weight: 600;
margin-bottom: 1rem;
margin-left: 1rem;
}
.hero h1 {
font-size: 3rem;
font-weight: 800;
margin-bottom: 1.5rem;
line-height: 1.2;
background: linear-gradient(135deg, var(--primary) 0%, var(--accent) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.hero-subtitle {
font-size: 1.25rem;
color: var(--text-light);
margin-bottom: 2rem;
max-width: 600px;
margin-left: auto;
margin-right: auto;
}
.hero-cta {
display: flex;
gap: 1rem;
justify-content: center;
margin-bottom: 3rem;
}
.btn-primary {
background: var(--primary);
color: white;
padding: 1rem 2rem;
border-radius: 8px;
text-decoration: none;
font-weight: 600;
display: inline-flex;
align-items: center;
gap: 0.5rem;
transition: all 0.3s ease;
}
.btn-primary:hover {
background: var(--primary-dark);
transform: translateY(-2px);
box-shadow: var(--shadow-lg);
}
.btn-secondary {
background: transparent;
color: var(--primary);
padding: 1rem 2rem;
border: 2px solid var(--primary);
border-radius: 8px;
text-decoration: none;
font-weight: 600;
transition: all 0.3s ease;
}
.btn-secondary:hover {
background: var(--primary);
color: white;
}
/* Search Styles */
.hero-search {
margin: 2rem 0;
width: 100%;
max-width: 600px;
margin-left: auto;
margin-right: auto;
}
.search-container {
position: relative;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 1rem;
}
.search-box {
width: 100%;
max-width: 500px;
padding: 1rem 1.5rem;
font-size: 1rem;
border: 2px solid var(--border);
border-radius: 50px;
outline: none;
transition: all 0.3s ease;
background: var(--bg-white);
color: var(--text-dark);
box-shadow: var(--shadow);
}
.search-box:focus {
border-color: var(--primary);
box-shadow: 0 4px 20px rgba(111, 66, 193, 0.2);
transform: translateY(-2px);
}
.search-box::placeholder {
color: var(--text-light);
}
.search-results {
max-width: 500px;
margin: 0 auto;
background: var(--bg-white);
border-radius: 12px;
box-shadow: var(--shadow-lg);
max-height: 400px;
overflow: hidden;
display: none;
position: relative;
z-index: 100;
border: 1px solid var(--border);
}
.search-results-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem;
border-bottom: 1px solid var(--border);
background-color: var(--bg-light);
}
.results-count {
color: var(--text-light);
font-size: 0.9rem;
font-weight: 600;
}
.close-results {
background: none;
border: none;
font-size: 1.5rem;
color: var(--text-light);
cursor: pointer;
padding: 0;
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
transition: all 0.2s ease;
}
.close-results:hover {
background-color: var(--border);
color: var(--text-dark);
}
.docs-search-results-list {
max-height: 300px;
overflow-y: auto;
}
.search-result-item {
padding: 1rem;
border-bottom: 1px solid var(--border);
cursor: pointer;
transition: background-color 0.2s ease;
color: var(--text-dark);
text-decoration: none;
display: block;
}
.search-result-item:hover {
background-color: var(--bg-light);
}
.search-result-item:last-child {
border-bottom: none;
}
.search-result-title {
font-weight: 600;
color: var(--primary);
margin-bottom: 0.5rem;
font-size: 1rem;
}
.search-result-content {
color: var(--text-light);
font-size: 0.9rem;
line-height: 1.4;
}
.search-result-content mark {
background-color: var(--accent);
color: var(--text-dark);
padding: 0.1em 0.2em;
border-radius: 2px;
}
.no-results {
padding: 2rem;
text-align: center;
color: var(--text-light);
}
/* Mobile responsive for search */
@media (max-width: 768px) {
.hero-search {
margin: 1.5rem 0;
}
.search-box {
font-size: 0.9rem;
padding: 0.875rem 1.25rem;
}
.search-results {
margin: 0 1rem;
max-width: calc(100% - 2rem);
}
}
@media (max-width: 480px) {
.search-box {
font-size: 0.85rem;
padding: 0.75rem 1rem;
}
}
/* Quick Stats */
.quick-stats {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 2rem;
max-width: 800px;
margin: 0 auto;
}
/* Desktop: 4 columns for stats */
@media (min-width: 768px) {
.quick-stats {
grid-template-columns: repeat(4, 1fr);
gap: 1.5rem;
}
}
.stat {
text-align: center;
}
.stat-number {
font-size: 2.5rem;
font-weight: 700;
color: var(--primary);
margin-bottom: 0.5rem;
}
.stat-label {
color: var(--text-dark);
font-size: 0.875rem;
}
/* Problem Section */
.problem-section {
padding: 4rem 2rem;
background: var(--bg-white);
}
.section-content {
max-width: 1200px;
margin: 0 auto;
}
.section-header {
text-align: center;
margin-bottom: 3rem;
}
.section-header h2 {
font-size: 2.5rem;
font-weight: 700;
margin-bottom: 1rem;
color: var(--text-dark);
}
.section-header p {
font-size: 1.125rem;
color: var(--text-light);
max-width: 600px;
margin: 0 auto;
}
.problem-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
margin-bottom: 3rem;
}
.problem-card {
background: var(--bg-light);
padding: 2rem;
border-radius: 12px;
transition: all 0.3s ease;
}
.problem-card:hover {
transform: translateY(-5px);
box-shadow: var(--shadow-lg);
}
.problem-icon {
font-size: 2.5rem;
margin-bottom: 1rem;
}
.problem-card h3 {
font-size: 1.25rem;
margin-bottom: 0.75rem;
color: var(--text-dark);
}
.problem-card p {
color: var(--text-light);
font-size: 0.875rem;
}
/* Solution Section */
.solution-section {
padding: 4rem 2rem;
background: var(--bg-light);
}
.solution-showcase {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 4rem;
align-items: center;
margin-bottom: 4rem;
}
.solution-showcase:nth-child(even) {
direction: rtl;
}
.solution-showcase:nth-child(even) .showcase-content {
direction: ltr;
}
.showcase-content h3 {
font-size: 2rem;
margin-bottom: 1rem;
color: var(--text-dark);
}
.showcase-content p {
color: var(--text-light);
margin-bottom: 1.5rem;
}
.feature-list {
list-style: none;
}
.feature-list li {
padding: 0.75rem 0;
color: var(--text-dark);
display: flex;
align-items: center;
gap: 0.75rem;
}
.feature-list li::before {
content: "✓";
display: inline-block;
width: 24px;
height: 24px;
background: var(--success);
color: white;
border-radius: 50%;
text-align: center;
line-height: 24px;
flex-shrink: 0;
}
.screenshot-placeholder {
background: var(--bg-white);
border: 2px dashed var(--border);
border-radius: 12px;
padding: 4rem 2rem;
text-align: center;
color: var(--text-light);
font-style: italic;
min-height: 400px;
display: flex;
align-items: center;
justify-content: center;
}
.mobile-screenshot {
max-width: 500px;
max-height: 500px;
width: auto;
height: auto;
border-radius: 12px;
box-shadow: var(--shadow-lg);
}
/* Power Tools Grid */
.tools-section {
padding: 4rem 2rem;
background: var(--bg-white);
}
.tools-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 2rem;
margin-top: 3rem;
}
.tool-card {
background: var(--bg-white);
border: 1px solid var(--border);
border-radius: 12px;
padding: 2rem;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.tool-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: linear-gradient(90deg, var(--primary) 0%, var(--accent) 100%);
transform: translateX(-100%);
transition: transform 0.3s ease;
}
.tool-card:hover::before {
transform: translateX(0);
}
.tool-card:hover {
box-shadow: var(--shadow-lg);
transform: translateY(-5px);
}
.tool-header {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 1rem;
}
.tool-icon {
font-size: 2rem;
width: 48px;
height: 48px;
background: var(--bg-light);
display: flex;
align-items: center;
justify-content: center;
border-radius: 12px;
}
.tool-card h3 {
font-size: 1.25rem;
color: var(--text-dark);
margin-bottom: 0.5rem;
}
.tool-description {
color: var(--text-light);
margin-bottom: 1rem;
font-size: 0.875rem;
}
.tool-features {
list-style: none;
font-size: 0.875rem;
}
.tool-features li {
padding: 0.5rem 0;
color: var(--text-dark);
display: flex;
align-items: center;
gap: 0.5rem;
}
.tool-features li::before {
content: "→";
color: var(--primary);
font-weight: bold;
}
.tool-cta {
margin-top: 1.5rem;
display: flex;
gap: 0.75rem;
flex-wrap: wrap;
}
.tool-cta .btn-secondary {
padding: 0.5rem 1rem;
font-size: 0.875rem;
border-width: 1px;
}
/* Integration Section */
.integration-section {
padding: 4rem 2rem;
background: var(--bg-light);
}
.integration-visual {
max-width: 800px;
margin: 3rem auto;
text-align: center;
}
.integration-diagram {
background: var(--bg-white);
border-radius: 12px;
padding: 3rem;
box-shadow: var(--shadow-lg);
}
/* Testimonial Section */
.testimonial-section {
padding: 4rem 2rem;
background: var(--primary);
color: white;
text-align: center;
}
.testimonial-content {
max-width: 800px;
margin: 0 auto;
}
.testimonial-section h2 {
color: white;
margin-bottom: 2rem;
}
.testimonial-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
margin-top: 3rem;
}
.testimonial-card {
background: rgba(255, 255, 255, 0.1);
padding: 2rem;
border-radius: 12px;
backdrop-filter: blur(10px);
}
.testimonial-text {
font-style: italic;
margin-bottom: 1rem;
opacity: 0.9;
}
.testimonial-author {
font-weight: 600;
}
.testimonial-role {
font-size: 0.875rem;
opacity: 0.8;
}
/* Live Sites Grid */
.live-sites-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
margin-top: 2rem;
}
.site-card {
background: rgba(255, 255, 255, 0.1);
padding: 1.5rem;
border-radius: 12px;
backdrop-filter: blur(10px);
text-decoration: none;
color: white;
transition: all 0.3s ease;
display: flex;
align-items: flex-start;
gap: 1rem;
position: relative;
border: 1px solid rgba(255, 255, 255, 0.1);
}
.site-card:hover {
transform: translateY(-4px);
background: rgba(255, 255, 255, 0.15);
border-color: rgba(255, 255, 255, 0.2);
}
.site-card.featured-site {
border: 2px solid rgba(255, 255, 255, 0.3);
background: rgba(255, 255, 255, 0.15);
}
.site-badge {
position: absolute;
top: -8px;
right: 1rem;
background: var(--accent);
color: white;
padding: 0.25rem 0.75rem;
border-radius: 20px;
font-size: 0.75rem;
font-weight: 600;
}
.site-icon {
font-size: 2rem;
flex-shrink: 0;
}
.site-content {
flex: 1;
}
.site-name {
font-weight: 600;
font-size: 1.125rem;
margin-bottom: 0.5rem;
}
.site-desc {
font-size: 0.875rem;
opacity: 0.9;
margin-bottom: 0.75rem;
line-height: 1.4;
color: #dfbfe6;
}
.site-status {
font-size: 0.75rem;
color: #4ade80;
font-weight: 600;
}
.proof-stats h3 {
color: white;
margin-bottom: 1.5rem;
text-align: center;
}
.stats-mini-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: 1rem;
max-width: 600px;
margin: 0 auto;
}
.mini-stat {
text-align: center;
background: rgba(255, 255, 255, 0.1);
padding: 1rem;
border-radius: 8px;
backdrop-filter: blur(10px);
}
.mini-stat .stat-number {
font-size: 1.5rem;
font-weight: 700;
color: white;
margin-bottom: 0.25rem;
}
.mini-stat .stat-label {
font-size: 0.875rem;
opacity: 0.8;
}
/* CTA Section */
.cta-section {
padding: 4rem 2rem;
background: var(--bg-white);
text-align: center;
}
.cta-content {
max-width: 600px;
margin: 0 auto;
}
.cta-section h2 {
font-size: 2.5rem;
margin-bottom: 1rem;
color: var(--text-dark);
}
.cta-section p {
font-size: 1.125rem;
color: var(--text-light);
margin-bottom: 2rem;
}
.cta-buttons {
display: flex;
gap: 1rem;
justify-content: center;
}
/* Data Ownership Section */
.sovereignty-section {
padding: 4rem 2rem;
background: var(--bg-white);
}
.sovereignty-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
margin: 3rem 0;
}
.sovereignty-card {
text-align: center;
padding: 2rem;
background: var(--bg-light);
border-radius: 12px;
transition: all 0.3s ease;
}
.sovereignty-card:hover {
transform: translateY(-5px);
box-shadow: var(--shadow-lg);
}
.sovereignty-icon {
font-size: 3rem;
margin-bottom: 1rem;
}
.sovereignty-card h3 {
font-size: 1.5rem;
margin-bottom: 1rem;
color: var(--text-dark);
}
.comparison-visual {
max-width: 800px;
margin: 3rem auto;
text-align: center;
}
.comparison-visual h3 {
font-size: 1.75rem;
margin-bottom: 2rem;
}
.comparison-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
}
.comparison-item {
background: var(--bg-light);
padding: 2rem;
border-radius: 12px;
}
.comparison-item h4 {
font-size: 1.25rem;
margin-bottom: 1rem;
}
.comparison-list {
list-style: none;
text-align: left;
}
.comparison-list li {
padding: 0.5rem 0;
font-size: 0.95rem;
}
.comparison-list.bad li {
color: #dc3545;
}
.comparison-list.good li {
color: var(--success);
}
/* Pricing Section */
.pricing-section {
padding: 4rem 2rem;
background: var(--bg-light);
}
.pricing-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
margin: 3rem 0;
max-width: 1000px;
margin-left: auto;
margin-right: auto;
}
.pricing-card {
background: var(--bg-white);
border: 2px solid var(--border);
border-radius: 12px;
padding: 2rem;
text-align: center;
position: relative;
transition: all 0.3s ease;
}
.pricing-card:hover {
transform: translateY(-5px);
box-shadow: var(--shadow-lg);
}
.pricing-card.featured {
border-color: var(--primary);
transform: scale(1.05);
}
.pricing-badge {
position: absolute;
top: -12px;
left: 50%;
transform: translateX(-50%);
background: var(--primary);
color: white;
padding: 0.25rem 1rem;
border-radius: 20px;
font-size: 0.875rem;
font-weight: 600;
}
.pricing-header h3 {
font-size: 1.5rem;
margin-bottom: 1rem;
color: var(--text-dark);
}
.price {
font-size: 3rem;
font-weight: 700;
color: var(--primary);
margin-bottom: 0.5rem;
}
.price-period {
font-size: 1rem;
color: var(--text-light);
margin-bottom: 2rem;
}
.pricing-features {
list-style: none;
text-align: left;
margin-bottom: 2rem;
}
.pricing-features li {
padding: 0.75rem 0;
border-bottom: 1px solid var(--border);
color: var(--text-dark);
}
.pricing-note {
font-size: 0.875rem;
color: var(--text-light);
margin-top: 1rem;
}
.cost-comparison {
text-align: center;
max-width: 600px;
margin: 3rem auto 0;
padding: 2rem;
background: var(--bg-white);
border-radius: 12px;
box-shadow: var(--shadow);
}
.cost-comparison h3 {
font-size: 1.5rem;
margin-bottom: 1rem;
}
.cost-comparison p {
font-size: 1.125rem;
margin-bottom: 1rem;
}
.cost-comparison strong {
color: var(--primary);
}
.comparison-link {
color: var(--primary);
text-decoration: none;
font-weight: 600;
display: inline-flex;
align-items: center;
gap: 0.5rem;
transition: gap 0.3s ease;
}
.comparison-link:hover {
gap: 1rem;
}
/* Mobile Features Badge */
.mobile-badge {
display: inline-flex;
align-items: center;
gap: 0.5rem;
background: var(--success);
color: white;
padding: 0.5rem 1rem;
border-radius: 20px;
font-size: 0.875rem;
font-weight: 600;
margin: 0.5rem;
}
.footer {
background: var(--text-dark);
color: white;
padding: 3rem 2rem 1rem;
}
.footer-content {
max-width: 1200px;
margin: 0 auto;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 3rem;
margin-bottom: 2rem;
}
.footer-section h4 {
margin-bottom: 1rem;
color: white;
}
.footer-links {
list-style: none;
}
.footer-links li {
padding: 0.5rem 0;
}
.footer-links a {
color: rgba(255, 255, 255, 0.8);
text-decoration: none;
transition: color 0.3s ease;
}
.footer-links a:hover {
color: white;
}
.footer-bottom {
text-align: center;
padding-top: 2rem;
border-top: 1px solid rgba(255, 255, 255, 0.1);
color: rgba(255, 255, 255, 0.6);
font-size: 0.875rem;
}
/* Mobile Responsive */
@media (max-width: 1024px) {
.solution-showcase {
gap: 3rem;
}
.showcase-content h3 {
font-size: 1.75rem;
}
}
@media (max-width: 768px) {
.nav-links {
display: none;
}
.hero h1 {
font-size: 2rem;
}
.hero-subtitle {
font-size: 1rem;
}
.hero-cta {
flex-direction: column;
align-items: center;
}
.solution-showcase {
grid-template-columns: 1fr;
gap: 2rem;
text-align: center;
}
.solution-showcase:nth-child(even) {
direction: ltr;
}
.showcase-content {
order: 1;
}
.screenshot-placeholder {
order: 2;
padding: 2rem 1rem;
}
.mobile-screenshot {
max-width: 100%;
height: auto;
}
.tools-grid {
grid-template-columns: 1fr;
}
.cta-buttons {
flex-direction: column;
align-items: center;
}
}
</style>
</head>
<body>
<!-- Custom header for landing page -->
<header class="header">
<nav class="nav-container">
<div class="logo">Changemaker Lite</div>
<div class="nav-items">
<ul class="nav-links">
<li><a href="#features">Features</a></li>
<li><a href="#tools">Power Tools</a></li>
<li><a href="#sovereignty">Data Ownership</a></li>
<li><a href="#pricing">Pricing</a></li>
</ul>
<div class="theme-switch-wrapper">
<label class="theme-switch" for="theme-toggle">
<input type="checkbox" id="theme-toggle" />
<span class="slider"></span>
</label>
</div>
<a href="#get-started" class="cta-button">Get Started</a>
</div>
</nav>
</header>
<!-- Hero Section -->
<section class="hero">
<div class="hero-content">
<div class="hero-badge">🚀 Hardware Up This Site Served by Changemaker - Lite</div>
<h1>Power Tools for Modern Campaign Documentation</h1>
<p class="hero-subtitle">
Give your supporters instant answers at the door, on the phone, or in person. Turn your campaign website & knowledge into a searchable,
mobile-first documentation system that actually works in the field or at the party. No corporate middlemen; your data, your servers, <strong>your platform</strong>.
</p>
<div class="hero-cta">
<a href="/phil" class="btn-primary">
Philosophy
<span></span>
</a>
<a href="#tools" class="btn-secondary">Explore Tools</a>
</div>
<!-- Search Section -->
<div class="hero-search">
<div class="search-container">
<input type="text"
class="search-box"
id="docs-search-input"
placeholder="Search campaign tools & docs... (Ctrl+K)"
autocomplete="off">
</div>
<div class="search-results" id="docs-search-results">
<div class="search-results-header">
<span class="results-count"></span>
<button class="close-results" type="button">&times;</button>
</div>
<div class="docs-search-results-list"></div>
</div>
</div>
<div class="quick-stats">
<div class="stat">
<div class="stat-number">100%</div>
<div class="stat-label">Local Data Ownership</div>
</div>
<div class="stat">
<div class="stat-number">$0</div>
<div class="stat-label">Free to Self-Host</div>
</div>
<div class="stat">
<div class="stat-number">Canadian</div>
<div class="stat-label">Built by Locals</div>
</div>
<div class="stat">
<div class="stat-number">Open-Source</div>
<div class="stat-label">Built for Campaigns</div>
</div>
</div>
</div>
</div>
</section>
<!-- Problem Section -->
<section class="problem-section">
<div class="section-content">
<div class="section-header">
<h2>Your Canvassers Are Struggling</h2>
<p>Traditional campaign tools weren't built for the reality of door-to-door work</p>
</div>
<div class="problem-grid">
<div class="problem-card">
<div class="problem-icon">📱</div>
<h3>Can't Find Answers Fast</h3>
<p>Voters ask tough questions. Your team fumbles through PDFs, emails, and scattered Google Docs while the voter loses interest.</p>
</div>
<div class="problem-card">
<div class="problem-icon">🗺️</div>
<h3>Disconnected Data</h3>
<p>Walk lists in one app, voter info in another, campaign policies somewhere else. Nothing talks to each other.</p>
</div>
<div class="problem-card">
<div class="problem-icon">💸</div>
<h3>Death by Subscription</h3>
<p>$100 here, $500 there. Before you know it, you're spending thousands monthly on tools that don't even work together.</p>
</div>
<div class="problem-card">
<div class="problem-icon">🔒</div>
<h3>No Data Control</h3>
<p>Your data is locked behind expensive subscriptions. Your strategies in corporate clouds. Your movement's future in someone else's hands.</p>
</div>
<div class="problem-card">
<div class="problem-icon">📵</div>
<h3>Not Mobile-Ready</h3>
<p>Desktop-first tools that barely work on phones. Canvassers struggling with tiny text and broken interfaces.</p>
</div>
<div class="problem-card">
<div class="problem-icon">🏢</div>
<h3>Foreign Dependencies</h3>
<p>US companies with US regulations. Your Canadian campaign data subject to foreign laws and surveillance.</p>
</div>
</div>
</div>
</section>
<!-- Solution Section -->
<section class="solution-section" id="features">
<div class="section-content">
<div class="section-header">
<h2>Documentation That Works at the Door</h2>
<p>Everything your team needs, instantly searchable, always accessible</p>
</div>
<div class="solution-showcase">
<div class="showcase-content">
<h3>Mobile-First Everything</h3>
<p>Built for phones first, because that's what your canvassers carry. Every feature, every interface, optimized for one-handed use in the field.</p>
<ul class="feature-list">
<li>Touch-optimized interfaces</li>
<li>Offline-capable after first load</li>
<li>Simple, easy to read, and clear buttons</li>
<li>One-thumb navigation</li>
<li>Instant load times</li>
</ul>
</div>
<div class="screenshot-placeholder">
<img src="assets/mobile_generic_view.png" alt="Phone showing mobile-optimized interface with large touch targets, clear typography, and instant search results" class="mobile-screenshot">
</div>
</div>
<div class="solution-showcase">
<div class="showcase-content">
<h3>Your Data, Your Servers, Your Rules</h3>
<p>Complete Data Ownership. Run it on Canadian soil, in your office, or anywhere you trust. No foreign surveillance, no corporate access, no compromises.</p>
<ul class="feature-list">
<li>100% self-hosted infrastructure</li>
<li>Canadian data residency</li>
<li>Complete export capabilities</li>
<li>No vendor lock-in ever</li>
<li>Privacy-first architecture</li>
</ul>
</div>
<div class="screenshot-placeholder">
<img src="assets/homepage_square.png" alt="Server dashboard showing Canadian hosting location, data ownership controls, and privacy settings" class="mobile-screenshot">
</div>
</div>
<div class="solution-showcase">
<div class="showcase-content">
<h3>Instant Search Everything</h3>
<p>Your entire campaign knowledge base at your fingertips. Policy positions, talking points, FAQs - all searchable in milliseconds.</p>
<ul class="feature-list">
<li>Full-text search across all documentation</li>
<li>Smart categorization and tagging</li>
<li>Works offline after first load</li>
<li>Mobile-optimized interface</li>
</ul>
</div>
<div class="screenshot-placeholder">
<img src="assets/search_square.png" alt="Mobile view showing instant search results for healthcare policy with highlighted snippets and quick access buttons" class="mobile-screenshot">
</div>
</div>
<div class="solution-showcase">
<div class="showcase-content">
<h3>Interactive Canvassing Maps</h3>
<p>See everything about a neighborhood before you knock. Previous interactions, support levels, local issues - all on one map.</p>
<ul class="feature-list">
<li>Real-time location tracking</li>
<li>Color-coded support levels</li>
<li>Add notes directly from the field</li>
<li>Track door knocks & interactions</li>
</ul>
</div>
<div class="screenshot-placeholder">
<img src="assets/map_square.gif" alt="Map interface showing color-coded houses, with popup showing voter details and previous interaction history" class="mobile-screenshot">
</div>
</div>
<div class="solution-showcase">
<div class="showcase-content">
<h3>Living Documentation</h3>
<p>Your campaign evolves daily. Your documentation should too. Update once, everyone gets it instantly.</p>
<ul class="feature-list">
<li>Real-time collaborative editing</li>
<li>Version control and history</li>
<li>Automatic mobile optimization</li>
<li>Beautiful, branded output</li>
<li>Thousands of plugins available</li>
<li>Local AI</li>
</ul>
</div>
<div class="screenshot-placeholder">
<img src="assets/coder_square.png" alt="Split view showing markdown editor on left, live preview on right with campaign branding" class="mobile-screenshot">
</div>
</div>
<div class="solution-showcase">
<div class="showcase-content">
<h3>Beautiul Websites</h3>
<p>Build and deploy beautiful websites & documentation using the tools already used by the worlds largest organizations.</p>
<ul class="feature-list">
<li>Social media cards</li>
<li>Fully customizable</li>
<li>Custom pages and landers</li>
<li>Integrated blogging</li>
<li>Supports 60+ languages</li>
</ul>
</div>
<div class="screenshot-placeholder">
<img src="assets/built.png" alt="Map interface showing color-coded houses, with popup showing voter details and previous interaction history" class="mobile-screenshot">
</div>
</div>
</div>
</section>
<!-- Power Tools Section -->
<section class="tools-section" id="tools">
<div class="section-content">
<div class="section-header">
<h2>Your Complete Campaign Power Tool Suite</h2>
<p>Everything works together. No integrations needed. No monthly fees.</p>
</div>
<div style="position: relative; padding-top: 56.25%; margin: 2rem 0;">
<iframe
src="https://customer-1ebw5tv06sxrrq32.cloudflarestream.com/33e0b6033cbc3c22d91df18ba867fe95/iframe?muted=true&preload=true&loop=true&autoplay=true&poster=https%3A%2F%2Fcustomer-1ebw5tv06sxrrq32.cloudflarestream.com%2F33e0b6033cbc3c22d91df18ba867fe95%2Fthumbnails%2Fthumbnail.jpg%3Ftime%3D%26height%3D600"
loading="lazy"
style="border: none; position: absolute; top: 0; left: 0; height: 100%; width: 100%;"
allow="accelerometer; gyroscope; autoplay; encrypted-media; picture-in-picture;"
allowfullscreen="true"
></iframe>
</div>
<div class="tools-grid">
<div class="tool-card">
<div class="tool-header">
<div class="tool-icon">📝</div>
<div>
<h3>Smart Documentation Hub</h3>
<div class="tool-description">MkDocs + Code Server</div>
mkdocs/docs/blog </div>
</div>
<p>Create beautiful, searchable documentation that your team will actually use.</p>
<ul class="tool-features">
<li>Instant search across everything</li>
<li>Mobile-first responsive design</li>
<li>Automatic table of contents</li>
<li>Deep linking to any section</li>
</ul>
<div class="tool-cta">
<a href="/services/mkdocs/" class="btn-secondary">Learn More</a>
<a href="/services/code-server/" class="btn-secondary">Code Server</a>
</div>
</div>
<div class="tool-card">
<div class="tool-header">
<div class="tool-icon">🗺️</div>
<div>
<h3>BNKops Map</h3>
<div class="tool-description">Interactive Canvassing System</div>
</div>
</div>
<p>Turn voter data into visual intelligence your canvassers can use.</p>
<ul class="tool-features">
<li>Real-time GPS tracking</li>
<li>Support level heat maps</li>
<li>Instant data entry</li>
<li>Offline-capable</li>
</ul>
<div class="tool-cta">
<a href="/services/map/" class="btn-secondary">Learn More</a>
</div>
</div>
<div class="tool-card">
<div class="tool-header">
<div class="tool-icon">📊</div>
<div>
<h3>Voter Database</h3>
<div class="tool-description">NocoDB Spreadsheet Interface</div>
</div>
</div>
<p>Manage voter data like a spreadsheet, access it like a database.</p>
<ul class="tool-features">
<li>Familiar Excel-like interface</li>
<li>Custom forms for data entry</li>
<li>Advanced filtering & search</li>
<li>API access for automation</li>
</ul>
<div class="tool-cta">
<a href="/services/nocodb/" class="btn-secondary">Learn More</a>
</div>
</div>
<div class="tool-card">
<div class="tool-header">
<div class="tool-icon">📧</div>
<div>
<h3>Email Command Center</h3>
<div class="tool-description">Listmonk Email Platform</div>
</div>
</div>
<p>Professional email campaigns without the professional price tag.</p>
<ul class="tool-features">
<li>Unlimited subscribers</li>
<li>Beautiful templates</li>
<li>Open & click tracking</li>
<li>Automated sequences</li>
</ul>
<div class="tool-cta">
<a href="/services/listmonk/" class="btn-secondary">Learn More</a>
</div>
</div>
<div class="tool-card">
<div class="tool-header">
<div class="tool-icon">🤖</div>
<div>
<h3>Campaign Automation</h3>
<div class="tool-description">n8n Workflow Engine</div>
</div>
</div>
<p>Automate repetitive tasks so your team can focus on voters.</p>
<ul class="tool-features">
<li>Visual workflow builder</li>
<li>Connect any service</li>
<li>Trigger-based automation</li>
<li>No coding required</li>
</ul>
<div class="tool-cta">
<a href="/services/n8n/" class="btn-secondary">Learn More</a>
</div>
</div>
<div class="tool-card">
<div class="tool-header">
<div class="tool-icon">🗃️</div>
<div>
<h3>Version Control</h3>
<div class="tool-description">Gitea Repository</div>
</div>
</div>
<p>Track changes, collaborate safely, and never lose work again.</p>
<ul class="tool-features">
<li>Full version history</li>
<li>Collaborative editing</li>
<li>Backup everything</li>
<li>Roll back changes</li>
</ul>
<div class="tool-cta">
<a href="/services/gitea/" class="btn-secondary">Learn More</a>
</div>
</div>
</div>
</div>
</section>
<!-- Data Ownership Section -->
<section class="sovereignty-section" id="sovereignty">
<div class="section-content">
<div class="section-header">
<h2>Canadian Tech for Canadian Campaigns</h2>
<p>Why trust your movement's future to foreign corporations?</p>
</div>
<div class="sovereignty-grid">
<div class="sovereignty-card">
<div class="sovereignty-icon">🇨🇦</div>
<h3>100% Canadian</h3>
<p>Built in Edmonton, Alberta. Supported by Canadian developers. Hosted on Canadian soil. Subject only to Canadian law.</p>
</div>
<div class="sovereignty-card">
<div class="sovereignty-icon">🔐</div>
<h3>True Ownership</h3>
<p>Your data never leaves your control. Export everything anytime. No algorithms, no surveillance, no corporate oversight.</p>
</div>
<div class="sovereignty-card">
<div class="sovereignty-icon">🛡️</div>
<h3>Privacy First</h3>
<p>Built to respect privacy from day one. Your supporters' data protected by design, not by policy.</p>
</div>
</div>
<div class="comparison-visual">
<h3>The Sovereignty Difference</h3>
<div class="comparison-grid">
<div class="comparison-item">
<h4>US Corporate Platforms</h4>
<ul class="comparison-list bad">
<li>❌ Subject to Patriot Act</li>
<li>❌ NSA surveillance</li>
<li>❌ Corporate data mining</li>
<li>❌ Foreign jurisdiction</li>
</ul>
</div>
<div class="comparison-item">
<h4>Changemaker Lite</h4>
<ul class="comparison-list good">
<li>✅ Canadian sovereignty</li>
<li>✅ Zero surveillance</li>
<li>✅ Complete privacy</li>
<li>✅ Your servers, your rules</li>
</ul>
</div>
</div>
</div>
</div>
</section>
<!-- Pricing Section -->
<section class="pricing-section" id="pricing">
<div class="section-content">
<div class="section-header">
<h2>Simple, Transparent Pricing</h2>
<p>No hidden fees. No usage limits. No surprises.</p>
</div>
<div class="pricing-grid">
<div class="pricing-card">
<div class="pricing-header">
<h3>Self-Hosted</h3>
<div class="price">$0</div>
<div class="price-period">forever</div>
</div>
<ul class="pricing-features">
<li>✓ All 11 campaign tools</li>
<li>✓ Unlimited users</li>
<li>✓ Unlimited data</li>
<li>✓ Complete documentation</li>
<li>✓ Community support</li>
<li>✓ Your infrastructure</li>
<li>✓ 100% open source</li>
</ul>
<a href="/build" class="btn-secondary">Installation Guide</a>
<p class="pricing-note">Perfect for tech-savvy campaigns</p>
</div>
<div class="pricing-card featured">
<div class="pricing-badge">Most Popular</div>
<div class="pricing-header">
<h3>Pre-Configured Server</h3>
<div class="price">Contact</div>
<div class="price-period">for pricing</div>
</div>
<ul class="pricing-features">
<li>✓ Everything in Self-Hosted</li>
<li>✓ Pre-installed & configured</li>
<li>✓ Hardware included</li>
<li>✓ 30-minute setup</li>
<li>✓ Training included</li>
<li>✓ Canadian support</li>
<li>✓ Ongoing updates</li>
</ul>
<a href="https://bnkops.com/hardware" class="btn-primary">Get a Quote</a>
<p class="pricing-note">Ready to use out of the box</p>
</div>
<div class="pricing-card">
<div class="pricing-header">
<h3>Managed Hosting</h3>
<div class="price">Custom</div>
<div class="price-period">monthly</div>
</div>
<ul class="pricing-features">
<li>✓ We handle everything</li>
<li>✓ Canadian data centers</li>
<li>✓ Daily backups</li>
<li>✓ 24/7 monitoring</li>
<li>✓ Security updates</li>
<li>✓ Priority support</li>
<li>✓ Still your data</li>
</ul>
<a href="https://bnkops.com/contact" class="btn-secondary">Contact Sales</a>
<p class="pricing-note">For larger campaigns</p>
</div>
</div>
<div class="cost-comparison">
<h3>Compare Your Savings</h3>
<p>Average campaign using corporate tools: <strong>$1,200-$4,000/month</strong></p>
<p>Same capabilities with Changemaker Lite: <strong>$0 (self-hosted)</strong></p>
<a href="/cost-comparison" class="comparison-link">See detailed cost breakdown →</a>
</div>
</div>
</section>
<!-- Integration Section -->
<section class="integration-section" id="integration">
<div class="section-content">
<div class="section-header">
<h2>Everything Works Together</h2>
<p>One login. One system. Infinite possibilities.</p>
</div>
<div class="integration-visual">
<div class="integration-diagram">
<div class="screenshot-placeholder">
<img src="assets/loop.png" alt="All systems communicate and build on one another" class="mobile-screenshot">
</div>
</div>
<p style="margin-top: 2rem; color: var(--text-light); font-size: 0.875rem;">
🎯 30-minute setup • 🔒 Your data stays yours • 🚀 No monthly fees
</p>
</div>
</div>
</section>
<!-- Live Examples Section -->
<section class="testimonial-section">
<div class="testimonial-content">
<h2>Real Sites, Real Results</h2>
<p style="text-align: center; margin-bottom: 3rem; color: var(--text-dark);">
Live sites powered by Changemaker Lite in production today
</p>
<div class="live-sites-grid">
<a href="https://pridecorner.ca/" target="_blank" class="site-card">
<div class="site-icon">🏳️‍🌈</div>
<div class="site-content">
<div class="site-name">Pride Corner</div>
<div class="site-desc">Community hub for LGBTQ+ advocacy and resources</div>
<div class="site-status">✓ Live</div>
</div>
</a>
<a href="https://publicinterestalberta.org/" target="_blank" class="site-card">
<div class="site-icon">🏛️</div>
<div class="site-content">
<div class="site-name">Public Interest Alberta</div>
<div class="site-desc">Policy advocacy and democratic engagement</div>
<div class="site-status">✓ Live</div>
</div>
</a>
<a href="https://lindalindsay.org/" target="_blank" class="site-card">
<div class="site-icon">🗳️</div>
<div class="site-content">
<div class="site-name">Linda Lindsay</div>
<div class="site-desc">Progressive political campaign platform</div>
<div class="site-status">✓ Live</div>
</div>
</a>
<a href="https://albertademocracytaskforce.org/" target="_blank" class="site-card">
<div class="site-icon">🤝</div>
<div class="site-content">
<div class="site-name">Alberta Democracy Taskforce</div>
<div class="site-desc">Defending democratic rights and freedoms</div>
<div class="site-status">✓ Live</div>
</div>
</a>
<a href="https://bnkops.com/" target="_blank" class="site-card featured-site">
<div class="site-badge">Platform Provider</div>
<div class="site-icon"></div>
<div class="site-content">
<div class="site-name">BNKops</div>
<div class="site-desc">Liberation technology and hosting services</div>
<div class="site-status">✓ Live</div>
</div>
</a>
</div>
<div class="proof-stats" style="margin-top: 3rem;">
<h3>Live Performance Metrics</h3>
<div class="stats-mini-grid">
<div class="mini-stat">
<div class="stat-number">5+</div>
<div class="stat-label">Live sites</div>
</div>
<div class="mini-stat">
<div class="stat-number">24/7</div>
<div class="stat-label">Uptime</div>
</div>
<div class="mini-stat">
<div class="stat-number">$0</div>
<div class="stat-label">Monthly fees</div>
</div>
<div class="mini-stat">
<div class="stat-number">100%</div>
<div class="stat-label">Data ownership</div>
</div>
</div>
</div>
</div>
</section>
<!-- CTA Section -->
<section class="cta-section" id="get-started">
<div class="cta-content">
<h2>Ready to Power Up Your Campaign?</h2>
<p>Join hundreds of campaigns using open-source tools to win elections and save money.</p>
<div class="cta-buttons">
<a href="mailto:cmlite@bnkops.ca?subject=Request%20to%20Chat%20-%20CMLITE&body=Hi%20CMlite%20Team%2C%20I%20would%20like%20to%20chat!%20Please%20send%20me%20a%20email%20back.%20Cheers%2C%20" class="btn-primary">Schedule a Chat</a>
<a href="/build" class="btn-secondary">Read Documentation</a>
</div>
<p style="margin-top: 2rem; color: var(--text-light); font-size: 0.875rem;">
🎯 30-minute setup • 🔒 Your data stays yours • 🚀 No monthly fees
</p>
</div>
</section>
<script src="https://unpkg.com/lunr@2.3.9/lunr.min.js"></script>
<script>
// Inline MkDocs search implementation
class MkDocsSearch {
constructor() {
this.searchIndex = null;
this.searchDocs = null;
this.initialized = false;
this.debounceTimeout = null;
}
async initialize() {
try {
// Try to load search index
const response = await fetch('search/search_index.json');
if (!response.ok) throw new Error('Failed to load search index');
const searchData = await response.json();
// Build Lunr index
this.searchIndex = lunr(function() {
this.ref('location');
this.field('title', { boost: 10 });
this.field('text');
searchData.docs.forEach(doc => {
this.add(doc);
});
});
this.searchDocs = searchData.docs;
this.initialized = true;
return true;
} catch (error) {
console.error('Failed to initialize search:', error);
return false;
}
}
search(query) {
if (!this.initialized || !query || query.length < 2) return [];
try {
const results = this.searchIndex.search(query);
return results.slice(0, 10).map(result => {
const doc = this.searchDocs.find(d => d.location === result.ref);
if (!doc) return null;
return {
...doc,
score: result.score,
url: doc.location,
snippet: this.extractSnippet(doc.text, query)
};
}).filter(Boolean);
} catch (error) {
console.error('Search error:', error);
return [];
}
}
extractSnippet(text, query, maxLength = 150) {
const lowerText = text.toLowerCase();
const lowerQuery = query.toLowerCase();
const index = lowerText.indexOf(lowerQuery);
if (index === -1) {
return text.substring(0, maxLength) + '...';
}
const start = Math.max(0, index - 50);
const end = Math.min(text.length, index + query.length + 100);
let snippet = text.substring(start, end);
if (start > 0) snippet = '...' + snippet;
if (end < text.length) snippet = snippet + '...';
// Highlight the search term
const regex = new RegExp(`(${query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
snippet = snippet.replace(regex, '<mark>$1</mark>');
return snippet;
}
}
// Initialize search when page loads
document.addEventListener('DOMContentLoaded', async () => {
const search = new MkDocsSearch();
const searchInput = document.getElementById('docs-search-input');
const searchResults = document.getElementById('docs-search-results');
const resultsContainer = searchResults.querySelector('.docs-search-results-list');
const resultsCount = searchResults.querySelector('.results-count');
const closeBtn = searchResults.querySelector('.close-results');
// Initialize search index
await search.initialize();
// Handle search input
searchInput.addEventListener('input', (e) => {
clearTimeout(search.debounceTimeout);
search.debounceTimeout = setTimeout(() => {
const query = e.target.value.trim();
if (!query || query.length < 2) {
searchResults.style.display = 'none';
return;
}
const results = search.search(query);
if (results.length === 0) {
resultsContainer.innerHTML = '<div class="no-results">No results found</div>';
resultsCount.textContent = 'No results';
} else {
resultsCount.textContent = `${results.length} result${results.length > 1 ? 's' : ''}`;
resultsContainer.innerHTML = results.map(result => `
<a href="${result.url}" class="search-result-item" style="text-decoration: none; display: block;">
<div class="search-result-title">${result.title}</div>
<div class="search-result-content">${result.snippet}</div>
</a>
`).join('');
}
searchResults.style.display = 'block';
}, 300);
});
// Keyboard shortcuts
document.addEventListener('keydown', (e) => {
if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
e.preventDefault();
searchInput.focus();
searchInput.select();
}
if (e.key === 'Escape' && searchResults.style.display !== 'none') {
searchResults.style.display = 'none';
searchInput.value = '';
searchInput.blur();
}
});
// Close button
closeBtn.addEventListener('click', () => {
searchResults.style.display = 'none';
searchInput.value = '';
});
// Click outside to close
document.addEventListener('click', (e) => {
if (!searchInput.contains(e.target) && !searchResults.contains(e.target)) {
searchResults.style.display = 'none';
}
});
});
</script>
<script>
// Theme switcher logic
const themeToggle = document.getElementById('theme-toggle');
const body = document.body;
const applyTheme = (theme) => {
if (theme === 'dark') {
body.classList.add('dark');
themeToggle.checked = true;
} else {
body.classList.remove('dark');
themeToggle.checked = false;
}
};
// Check for saved theme in localStorage
const savedTheme = localStorage.getItem('theme');
// Check for system preference
const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
if (savedTheme) {
applyTheme(savedTheme);
} else if (prefersDark) {
applyTheme('dark');
} else {
applyTheme('dark');
}
themeToggle.addEventListener('change', () => {
if (themeToggle.checked) {
applyTheme('dark');
localStorage.setItem('theme', 'dark');
} else {
applyTheme('light');
localStorage.setItem('theme', 'light');
}
});
// Add scroll effect to header
window.addEventListener('scroll', function() {
const header = document.querySelector('.header');
if (window.scrollY > 50) {
header.classList.add('scrolled');
} else {
header.classList.remove('scrolled');
}
});
// Smooth scrolling for anchor links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
// Add intersection observer for fade-in animations
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}
});
}, observerOptions);
// Observe all cards and sections
document.querySelectorAll('.problem-card, .tool-card, .solution-showcase, .testimonial-card').forEach(el => {
el.style.opacity = '0';
el.style.transform = 'translateY(20px)';
el.style.transition = 'opacity 0.6s ease, transform 0.6s ease';
observer.observe(el);
});
</script>
</body>
</html>