bnkops.changemaker/mkdocs/site/overrides/home-cm-archive.html
2025-05-14 14:21:31 -06:00

1805 lines
51 KiB
HTML

{% extends "main.html" %}
{% block content %}
<style>
.typewriter-container {
min-height: 7.2em; /* Increased to accommodate three lines */
position: relative;
margin: 1rem 0;
overflow: hidden;
transition: height 0.3s ease-in-out;
position: relative;
z-index: 0;
.cursor, #cursor {
display: inline-block;
width: 2px;
background-color: var(--bnk-yellow);
animation: blink-cursor 0.7s steps(1) infinite;
height: 1.4em;
vertical-align: text-top;
margin-left: 1px;
position: absolute; /* Make sure it's absolutely positioned */
z-index: 1; /* Keep it above text */
}
.typewriter-text, #typewriter-text {
color: var(--bnk-text);
font-weight: normal;
font-size: 1.25rem;
line-height: 1.4;
margin: 0;
padding: 0;
min-height: 4.2em; /* Set for three lines of text */
width: 100%;
white-space: pre-wrap;
word-break: break-word;
display: inline;
}
</style>
<style>
/* Base styling */
:root {
--bnk-dark-bg: #1e2127;
--bnk-yellow: #ffd700;
--bnk-text: rgba(255, 255, 255, 0.87);
--bnk-text-dim: rgba(255, 255, 255, 0.7);
}
.md-content {
background: var(--bnk-dark-bg);
max-width: 100%;
padding: 0;
}
.md-main {
background: var(--bnk-dark-bg);
}
/* Terminal-style header section */
.terminal-header {
background: rgba(0, 0, 0, 0.2);
border: 1px solid rgba(255, 215, 0, 0.1);
border-radius: 8px;
padding: 1rem;
margin: 0 auto 2rem auto;
max-width: 600px;
height: 230px;
overflow: hidden;
font-family: 'Courier New', monospace;
position: relative;
}
/* Rest of terminal styles remain the same */
.terminal-header::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 25px;
background: rgba(255, 215, 0, 0.1);
border-bottom: 1px solid rgba(255, 215, 0, 0.1);
border-radius: 8px 8px 0 0;
}
.terminal-header::after {
content: '⚪ ⚪ ⚪';
position: absolute;
top: 4px;
left: 10px;
font-size: 12px;
color: rgba(255, 255, 255, 0.3);
}
.typing-effect {
position: relative;
color: var(--bnk-text-dim);
font-size: 0.8rem; /* Reduced from 0.9rem */
line-height: 1.2; /* Reduced from 1.5 */
margin: 0;
padding: 0;
opacity: 0;
margin-top: 5px; /* Reduced from 25px */
transform: translateY(20px);
}
.typing-effect.active {
opacity: 1;
transform: translateY(0);
transition: all 0.3s ease;
}
.typing-effect span {
color: var(--bnk-yellow);
}
.typing-effect::before {
content: '>';
color: var(--bnk-yellow);
margin-right: 10px;
}
.cursor {
display: inline-block;
width: 2px;
background-color: var(--bnk-yellow);
animation: blink-cursor 0.7s steps(1) infinite;
margin-left: 2px;
height: 1em;
vertical-align: bottom;
position: relative; /* Change from absolute to relative */
transform: translateY(1px); /* Add this to align with text */
}
.typewriter-text {
color: var(--bnk-text);
font-weight: normal;
font-size: 1.25rem;
line-height: 1.4;
margin: 0;
padding: 0;
min-height: 1.4em;
position: relative; /* Change from absolute to relative */
width: 100%;
white-space: pre-wrap;
word-break: break-word;
}
@keyframes blink-cursor {
50% { opacity: 0; }
}
@keyframes blink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
}
/* Enhanced main title */
h1 {
color: var(--bnk-yellow) !important;
font-weight: normal !important;
font-size: 2.5rem !important;
margin-bottom: 0.5rem !important;
text-align: center;
background: linear-gradient(
45deg,
var(--bnk-yellow),
#fff9c4,
var(--bnk-yellow)
);
background-size: 200% 200%;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
animation:
gradientFlow 8s ease infinite,
fadeInUp 0.8s ease forwards;
}
h2 {
color: var(--bnk-yellow) !important;
font-weight: normal !important;
font-size: 1.5rem !important;
margin: 1.5rem 0 0.75rem 0 !important;
opacity: 0;
transform: translateY(20px);
}
/* Text styling */
p {
color: var(--bnk-text);
opacity: 0;
transform: translateY(20px);
}
ul li {
color: var(--bnk-text);
opacity: 0;
transform: translateY(20px);
margin: 0.5rem 0;
}
/* Feature cards */
.feature-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 0.75rem;
margin: 0.75rem auto;
max-width: 1200px;
padding: 0 0.75rem;
}
.feature-card {
background: linear-gradient(
145deg,
rgba(255, 215, 0, 0.05),
rgba(255, 215, 0, 0.02)
);
border: 1px solid rgba(255, 215, 0, 0.1);
border-radius: 8px;
padding: 0.75rem;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
overflow: hidden;
}
.feature-card::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 8px;
background: linear-gradient(
45deg,
transparent,
rgba(255, 215, 0, 0.1),
transparent
);
transform: translateX(-100%);
transition: transform 0.6s ease;
}
.feature-card:hover {
transform: translateY(-5px);
border-color: var(--bnk-yellow);
box-shadow:
0 10px 20px rgba(0, 0, 0, 0.1),
0 0 0 1px rgba(255, 215, 0, 0.2);
}
.feature-card:hover::after {
transform: translateX(100%);
}
.feature-card h3 {
color: var(--bnk-yellow) !important;
margin: 0 0 0.5rem 0 !important;
font-size: 1.1rem !important;
}
.feature-card p {
margin: 0;
color: var(--bnk-text-dim);
}
.feature-card a {
color: var(--bnk-yellow);
text-decoration: none;
position: relative;
}
.feature-card a::after {
content: '';
position: absolute;
bottom: -2px;
left: 0;
width: 100%;
height: 1px;
background: var(--bnk-yellow);
transform: scaleX(0);
transform-origin: right;
transition: transform 0.3s ease;
}
.feature-card a:hover::after {
transform: scaleX(1);
transform-origin: left;
}
/* Emoji animation */
.emoji-float {
display: inline-block;
animation: float 3s ease-in-out infinite;
}
/* Section styling */
.section {
margin: 0.75rem 0;
padding: 0.75rem;
border-radius: 8px;
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 215, 0, 0.1);
}
/* Code blocks */
code {
background: rgba(255, 255, 255, 0.1);
padding: 0.2em 0.4em;
border-radius: 3px;
}
/* Animations */
@keyframes gradientFlow {
0% { background-position: 0% 50% }
50% { background-position: 100% 50% }
100% { background-position: 0% 50% }
}
@keyframes fadeInUp {
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes float {
0% { transform: translateY(0px); }
50% { transform: translateY(-5px); }
100% { transform: translateY(0px); }
}
/* Scroll reveal class */
.reveal {
opacity: 1 !important;
transform: translateY(0) !important;
transition: all 0.8s ease;
}
</style>
<style>
.highlight-feature {
background: linear-gradient(145deg, rgba(255, 215, 0, 0.1), rgba(255, 215, 0, 0.05));
border: 1px solid rgba(255, 215, 0, 0.2);
padding: 1.5rem;
border-radius: 8px;
margin: 2rem 0;
}
.savings-card {
background: linear-gradient(145deg, rgba(39, 174, 96, 0.1), rgba(39, 174, 96, 0.05));
border: 1px solid rgba(39, 174, 96, 0.2);
padding: 1rem;
border-radius: 8px;
margin: 1rem 0;
display: flex;
align-items: center;
gap: 1rem;
}
.savings-amount {
font-size: 1.5rem;
color: #27AE60;
font-weight: bold;
}
</style>
<style>
/* Update activist banner spacing */
.activist-banner {
padding: 1.5rem;
margin: 1.5rem 0;
}
.activist-grid {
gap: 1rem;
margin: 1.5rem 0;
}
.activist-card {
padding: 1.25rem;
min-width: 180px;
}
.activist-card .emoji {
margin-bottom: 0.75rem;
}
.manifesto {
margin-top: 1.5rem;
}
/* Update highlight feature spacing */
.highlight-feature {
padding: 1.25rem;
margin: 1rem 0;
}
.highlight-feature h2 {
margin: 0 0 0.75rem 0;
}
.savings-card {
padding: 0.75rem;
margin: 0.75rem 0;
gap: 0.75rem;
}
/* Responsive adjustments */
@media (max-width: 768px) {
.activist-grid {
gap: 0.75rem;
}
.activist-card {
padding: 1rem;
max-width: 280px;
}
}
</style>
<style>
.power-header {
text-align: center;
padding: 2rem 1rem;
background: linear-gradient(135deg, #333 0%, #555 20%, #ccc 40%, #fff 50%, #ccc 60%, #555 80%, #333 100%);
background-size: 200% 200%;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
animation: shine 5s linear infinite;
text-shadow:
0 0 1px rgba(255,255,255,0.1),
0 1px 3px rgba(0,0,0,0.3),
0 3px 5px rgba(0,0,0,0.2),
0 5px 10px rgba(0,0,0,0.25),
0 10px 10px rgba(0,0,0,0.2),
0 20px 20px rgba(0,0,0,0.15);
}
.power-header h1 {
font-size: 3.5rem;
margin-bottom: 0.5rem;
font-weight: 800;
letter-spacing: -0.05em;
}
.power-header p {
font-size: 1.8rem;
opacity: 0.9;
font-weight: 600;
}
@keyframes shine {
from { background-position: 200% center; }
to { background-position: -200% center; }
}
</style>
<!-- Update heading styles -->
<style>
/* Global heading styles to match Why Change Maker */
h1, h2, h3, h4, h5, h6 {
font-family: system-ui, -apple-system, sans-serif;
text-align: center;
background: linear-gradient(135deg, #333 0%, #555 20%, #ccc 40%, #fff 50%, #ccc 60%, #555 80%, #333 100%);
background-size: 200% 200%;
-webkit-background-clip: text;
background-clip: text;
color: transparent !important;
animation: shine 5s linear infinite;
text-shadow:
0 0 1px rgba(255,255,255,0.1),
0 1px 3px rgba(0,0,0,0.3),
0 3px 5px rgba(0,0,0,0.2),
0 5px 10px rgba(0,0,0,0.25),
0 10px 10px rgba(0,0,0,0.2),
0 20px 20px rgba(0,0,0,0.15);
}
h1 {
font-size: 3.5rem !important;
font-weight: 800 !important;
letter-spacing: -0.05em !important;
margin: 2rem 0 1rem !important;
line-height: 1.2 !important;
}
h2 {
font-size: 2.5rem !important;
font-weight: 700 !important;
letter-spacing: -0.03em !important;
margin: 1.5rem 0 1rem !important;
line-height: 1.3 !important;
}
h3 {
font-size: 1.8rem !important;
font-weight: 600 !important;
margin: 1rem 0 0.75rem !important;
}
/* Remove the old gradient styles */
.power-header {
padding: 2rem 1rem;
}
.power-header h1,
.power-header h2,
.power-header p {
/* Reset any existing styles to use the global heading styles */
background: inherit;
-webkit-background-clip: inherit;
background-clip: inherit;
animation: inherit;
}
/* Update animation keyframes */
@keyframes shine {
from { background-position: 200% center; }
to { background-position: -200% center; }
}
</style>
<style>
/* Update heading styles to be more selective */
.md-content > h1, /* Only top-level headers */
.md-content > h2,
.md-content > .power-header h1,
.md-content > .power-header h2 {
font-family: system-ui, -apple-system, sans-serif;
text-align: center;
background: linear-gradient(135deg, #FFD700 0%, #FFEC8B 20%, #FFD700 40%, #FFEC8B 50%, #FFD700 60%, #FFEC8B 80%, #FFD700 100%);
background-size: 200% 200%;
-webkit-background-clip: text;
background-clip: text;
color: transparent !important;
animation: shine 15s linear infinite;
text-shadow:
0 0 1px rgba(255,255,255,0.1),
0 1px 3px rgba(0,0,0,0.3),
0 3px 5px rgba(0,0,0,0.2),
0 5px 10px rgba(0,0,0,0.25),
0 10px 10px rgba(0,0,0,0.2),
0 20px 20px rgba(0,0,0,0.15);
font-size: 3.5rem !important;
font-weight: 800 !important;
letter-spacing: -0.05em !important;
margin: 2rem 0 1rem !important;
line-height: 1.2 !important;
}
/* Reset container heading styles to original gold */
.highlight-feature h2,
.feature-card h3,
.section h2 {
background: none !important;
-webkit-background-clip: unset !important;
background-clip: unset !important;
color: var(--bnk-yellow) !important;
text-shadow: none !important;
animation: none !important;
font-size: 1.5rem !important;
font-weight: normal !important;
letter-spacing: normal !important;
}
/* Keep original container heading sizes */
.highlight-feature h2 {
font-size: 1.5rem !important;
margin: 0 0 0.75rem 0 !important;
}
.feature-card h3 {
font-size: 1.1rem !important;
margin: 0 0 0.5rem 0 !important;
}
</style>
<style>
/* Update highlight feature grid layout */
.highlight-features-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(450px, 1fr));
gap: 1rem;
margin: 2rem 0;
}
.highlight-feature {
background: linear-gradient(145deg, rgba(255, 215, 0, 0.05), rgba(255, 215, 0, 0.02));
border: 1px solid rgba(255, 215, 0, 1);
padding: 1.25rem;
border-radius: 8px;
margin: 0; /* Remove individual margins */
height: 100%; /* Ensure equal height */
display: flex;
flex-direction: column;
}
/* Responsive adjustments */
@media (max-width: 920px) {
.highlight-features-grid {
grid-template-columns: 1fr;
}
.highlight-feature {
margin: 0.5rem 0;
}
}
</style>
<style>
/* Amber gold header with animation */
.power-header h1, .power-header h2 {
color: var(--bnk-yellow); /* Amber gold color */
text-shadow: 0 0 10px rgba(255, 215, 0, 0.5);
animation: glow 15s ease-in-out infinite alternate;
}
/* Glow animation */
@keyframes glow {
from {
text-shadow: 0 0 5px rgba(255, 215, 0, 0.5);
}
to {
text-shadow: 0 0 20px rgba(255, 215, 0, 1);
}
}
/* Animated paragraph container */
.animated-container {
opacity: 0;
transform: translateY(20px);
animation: fadeInUp 1s forwards;
}
/* Fade-in animation */
@keyframes fadeInUp {
to {
opacity: 1;
transform: translateY(0);
}
}
</style>
<!-- Add background to the entry header -->
<style>
.power-header.entry-header {
position: relative;
overflow: hidden;
min-height: 500px; /* Ensure the container is tall enough for the emoji */
}
.power-header.entry-header::before {
content: '✊';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 500px;
color: rgba(255, 215, 0, 0.5); /* Increase emoji opacity */
pointer-events: none;
user-select: none;
line-height: 1;
}
.power-header.entry-header h1 {
position: relative;
z-index: 1;
}
/* Style for "Bnkops Change Maker" */
.power-header .highlight-text {
color: var(--bnk-yellow); /* Shiny gold/amber color */
text-shadow: 0 0 10px rgba(255, 215, 0, 0.5);
animation: shine 15s linear infinite;
}
@keyframes shine {
0% {
background-position: 200% center;
}
50% {
background-position: -200% center;
}
100% {
background-position: 200% center;
}
}
</style>
<!-- Power header styles with metallic effect -->
<style>
.power-header.entry-header h3 {
/* Welcome to text */
color: rgba(255, 255, 255, 0.9) !important;
font-size: 1.5rem !important;
font-weight: normal !important;
text-shadow: none !important;
background: none !important;
-webkit-background-clip: initial !important;
background-clip: initial !important;
animation: none !important;
margin-bottom: 0.5rem !important;
}
.power-header.entry-header h1.highlight-text {
/* Metallic gold effect for main title */
background: linear-gradient(
135deg,
#ffd700 0%,
#fff6a9 10%,
#d4af37 20%,
#fff6a9 30%,
#ffd700 40%,
#fff6a9 50%,
#d4af37 60%,
#fff6a9 70%,
#ffd700 80%,
#fff6a9 90%,
#d4af37 100%
) !important;
-webkit-background-clip: text !important;
background-clip: text !important;
color: transparent !important;
text-shadow:
0 0 1px rgba(255, 215, 0, 0.2),
0 0 15px rgba(255, 215, 0, 0.3),
0 0 30px rgba(255, 215, 0, 0.1) !important;
font-weight: 800 !important;
font-size: 4rem !important;
letter-spacing: -0.02em !important;
animation: metallicShine 8s linear infinite !important;
background-size: 200% auto !important;
}
@keyframes metallicShine {
to {
background-position: 200% center;
}
}
</style>
<div class="md-content">
<!-- Update the entry header -->
<div class="power-header entry-header">
<h3>Welcome to</h3>
<h1 class="highlight-text">Change Maker</h1>
</div>
<!-- Main content with enhanced visual styling -->
<div class="animated-container hero-content">
<!-- Wrapper for the two containers -->
<div class="content-box-wrapper">
<!-- First paragraph with icon and highlight box -->
<div class="content-box">
<div class="icon-wrapper">
<span class="feature-icon">🚀</span>
</div>
<p class="highlight-text">
Turn any internet connected computer into a website server with open manuals to manage a full digital political campaign.
<span class="emphasis" style="font-weight: bold; color: #FFFFFF; text-shadow: 2px 2px 4px rgba(128, 0, 128, 0.5);">Or, you know, just a regular old blog.</span>
<a href="https://changemaker.bnkops.com/Free(ish)">For free(ish)</a>.
With everything running locally on your machine, there's simply no faster way to develop a website and grow your following.
<span class="emoji-float">😉</span>
</p>
</div>
<!-- Second paragraph with icon and highlight box -->
<div class="content-box">
<div class="icon-wrapper">
<span class="feature-icon">🔒</span>
</div>
<p class="highlight-text">
Your content is <span class="emphasis" style="font-weight: bold; color: #FFFFFF; text-shadow: 2px 2px 4px rgba(128, 0, 128, 0.5);">locally built, inherently secure, and remotely accessible</span> so you can keep control of your site; right down to the bare code. Never share server space with your competition again and stop
<a href="https://changemaker.bnkops.com/Why%20Change%20Maker/">funding corporate software</a>
that is antithetical to your morals. Publish your content on your terms; <span class="emphasis" style="font-weight: bold; color: #FFFFFF; text-shadow: 2px 2px 4px rgba(128, 0, 128, 0.5);">true freedom of speech.</span>
</p>
</div>
</div>
</div>
<form method="post" action="https://listmonk.bnkops.com/subscription/form" class="listmonk-form">
<div class="form-content">
<!-- Orbiting Text Elements -->
<div class="orbit-text" style="--start-rotation: 0deg;">✨ Stay in the Loop ✨</div>
<div class="orbit-text" style="--start-rotation: 120deg;">✨ Subscribe for Code ✨</div>
<div class="orbit-text" style="--start-rotation: 240deg;">✨ Get the Latest ✨</div>
<!-- Form Inputs -->
<input type="hidden" name="nonce" />
<input type="email" name="email" required placeholder="E-mail" />
<input type="text" name="name" placeholder="Name (optional)" />
<label>
<input id="038eb" type="checkbox" name="l" checked value="038eb469-e141-435d-86eb-2ab4df20cf9c" />
Weekly Releases and Updates
</label>
<!-- Subscribe Button -->
<div class="subscribe-container">
<input type="submit" value="Subscribe" />
</div>
</div>
</form>
<style>
.hero-content {
max-width: 1200px; /* Increased max-width to accommodate side-by-side */
margin: 2rem auto;
}
.content-box-wrapper {
display: flex;
gap: 1rem;
flex-wrap: wrap; /* Allows stacking on smaller screens */
}
.content-box {
background: linear-gradient(145deg, rgba(255, 215, 0, 0.05), rgba(255, 215, 0, 0.02));
border: 1px solid rgba(255, 215, 0, 0.1);
border-radius: 12px;
padding: 1.5rem;
margin: 0; /* Removed vertical margin */
display: flex;
align-items: flex-start;
gap: 1rem;
transition: transform 0.3s ease;
flex: 1; /* Allow equal growth */
min-width: 300px; /* Minimum width before stacking */
}
.content-box:hover {
transform: translateY(-2px);
border-color: rgba(255, 215, 0, 0.3);
}
.icon-wrapper {
background: rgba(255, 215, 0, 0.1);
border-radius: 50%;
padding: 1rem;
margin-top: 0.5rem;
flex-shrink: 0; /* Prevent icon from shrinking */
}
.feature-icon {
font-size: 1.5rem;
animation: float 3s ease-in-out infinite;
}
.highlight-text {
margin: 0;
line-height: 1.6;
}
.emphasis {
color: var(--bnk-yellow);
font-weight: 500;
}
@keyframes float {
0% { transform: translateY(0px); }
50% { transform: translateY(-5px); }
100% { transform: translateY(0px); }
}
/* Media query for mobile devices */
@media (max-width: 768px) {
.content-box {
flex: 1 1 100%; /* Take full width on mobile */
margin: 0.5rem 0; /* Add some vertical spacing when stacked */
}
}
</style>
<div class="power-header">
<h1>Build Your Power, Don't Rent It.</h1>
</div>
<!-- Moved Terminal Header here -->
<div class="terminal-header">
<div class="typing-effect">initializing documentation system<span class="cursor"></span></div>
<div class="typing-effect">checking dependencies...</div>
<div class="typing-effect"><span></span> site built ready to serve</div>
<div class="typing-effect"><span></span> newsletter configured ready</div>
<div class="typing-effect"><span></span> real-time preview active</div>
<div class="typing-effect"><span></span> editor built online </div>
<div class="typing-effect"><span></span> change maker ready!</div>
</div>
<style>
.activist-banner {
background: linear-gradient(145deg, rgba(255, 215, 0, 0.05), rgba(255, 215, 0, 0.02));
border-radius: 12px;
padding: 2rem;
margin: 2rem 0;
text-align: center;
}
.activist-grid {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 1.5rem;
margin: 2rem 0;
}
.activist-card {
background: rgba(45, 27, 77, 0.3);
border: 1px solid rgba(255, 215, 0, 0.1);
border-radius: 8px;
padding: 1.5rem;
min-width: 200px;
transform: translateY(0);
transition: all 0.3s ease;
}
.activist-card:hover {
transform: translateY(-5px);
border-color: var(--bnk-yellow);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
}
.activist-card .emoji {
font-size: 2.5rem;
margin-bottom: 1rem;
animation: float 3s ease-in-out infinite;
}
.activist-card .role {
color: var(--bnk-yellow);
font-size: 1.2rem;
font-weight: bold;
margin-bottom: 0.5rem;
}
.activist-card .action {
color: var(--bnk-text);
font-size: 0.9rem;
opacity: 0.9;
}
.manifesto {
font-size: 1.1rem;
color: var(--bnk-text);
margin-top: 2rem;
font-style: italic;
line-height: 1.6;
max-width: 600px;
margin-left: auto;
margin-right: auto;
}
@keyframes float {
0% { transform: translateY(0px); }
50% { transform: translateY(-10px); }
100% { transform: translateY(0px); }
}
@media (max-width: 768px) {
.activist-grid {
flex-direction: column;
align-items: center;
}
.activist-card {
width: 100%;
max-width: 300px;
}
}
</style>
<div class="highlight-features-grid">
<div class="highlight-feature">
<h2>🚀 NEW: Built-in Email, SMS, & Messengers Marketing</h2>
<p>Now includes Listmonk - a powerful, free alternative to MailChimp and Constant Contact. Send newsletters, manage subscribers, and run email campaigns without monthly fees.</p>
<div class="savings-card">
<div>💰</div>
<div>
<span class="savings-amount">Save $1,200+/year</span><br>
<small>vs. commercial email marketing tools</small>
</div>
</div>
</div>
<div class="highlight-feature">
<h2>🌐 Website Builder, Server, and Editor Hosting All-In-One.</h2>
<p>Professional website builder and hosting platform. No more WordPress fees or expensive site builders. Edit your sites code directly on device. Never share server space with your competition again. </p>
<div class="savings-card">
<div>💰</div>
<div>
<span class="savings-amount">Save $300+/year</span><br>
<small>vs. WordPress hosting & plugins</small>
</div>
</div>
</div>
<div class="highlight-feature">
<h2>📱 Mobile Tools & Apps</h2>
<p>Mobile-optimized tools for on-the-go campaign management. No app subscriptions needed. Write web pages on the fly on any device.</p>
<div class="savings-card">
<div>💰</div>
<div>
<span class="savings-amount">Save $500+/year</span><br>
<small>vs. mobile campaign tools</small>
</div>
</div>
</div>
<div class="highlight-feature" style="background: linear-gradient(145deg, rgba(255, 215, 0, 0.15), rgba(255, 215, 0, 0.1));">
<h2>💎 Total Campaign Savings</h2>
<p>Replace your entire campaign tech stack with one free, open-source platform.</p>
<div class="savings-card" style="background: linear-gradient(145deg, rgba(255, 215, 0, 0.1), rgba(255, 215, 0, 0.05));">
<div>🏆</div>
<div>
<span class="savings-amount">Save $2,200+/year</span><br>
<small>Total savings vs. commercial alternatives</small>
</div>
</div>
</div>
</div>
<style>
.terminal-window {
background: rgb(29, 31, 33);
border-radius: 4px;
padding: 1rem;
margin: 1rem 0;
position: relative;
font-family: monospace;
width: 100%;
max-width: 100%;
}
.terminal-window::before {
content: "⚪ ⚪ ⚪";
position: absolute;
top: 0.3rem;
left: 0.5rem;
font-size: 0.6rem;
color: rgba(255, 255, 255, 0.3);
}
.terminal-prompt {
color: rgb(255, 215, 0);
margin-bottom: 0.5rem;
font-size: 0.8rem;
white-space: nowrap;
text-shadow: 0 0 10px rgba(255, 215, 0, 0.3);
}
.progress-container {
width: 100%;
height: 16px;
background: rgba(0, 0, 0, 0.3);
border: 1px solid rgba(255, 215, 0, 0.2);
margin: 0.5rem 0;
position: relative;
overflow: visible;
}
.progress-bar {
height: 100%;
width: 0%;
background: rgba(255, 215, 0, 0.15);
transition: width 0.15s ease-out;
position: relative;
}
/* Tron-style grid effect */
.progress-bar::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background:
linear-gradient(90deg, rgba(255, 215, 0, 0.1) 1px, transparent 1px),
linear-gradient(0deg, rgba(255, 215, 0, 0.1) 1px, transparent 1px);
background-size: 8px 8px;
}
.progress-bar::after {
content: '';
position: absolute;
top: 0;
right: 0;
width: 2px;
height: 100%;
background: rgb(255, 215, 0);
box-shadow: 0 0 10px rgba(255, 215, 0, 0.5);
}
.progress-tooltip {
position: absolute;
top: -34px;
left: 75%;
transform: translateX(-100%);
background: rgba(29, 31, 33, 0.95);
border: 1px solid rgba(255, 215, 0, 0.3);
padding: 3px 6px;
border-radius: 3px;
font-size: 0.65rem;
color: rgba(255, 215, 0, 0.9);
opacity: 0;
transition: opacity 0.3s ease;
pointer-events: none;
box-shadow: 0 0 5px rgba(255, 215, 0, 0.1);
z-index: 1000;
width: max-content;
max-width: 150px;
}
/* Mobile-specific tooltip styling */
@media (max-width: 600px) {
.progress-tooltip {
display: flex;
flex-direction: column;
font-size: 0.6rem;
line-height: 1.2;
top: -38px;
text-align: left;
}
.tooltip-line1 {
margin-bottom: 2px;
}
}
.progress-tooltip::after {
content: '';
position: absolute;
bottom: -3px;
left: calc(100% - 10px);
width: 6px;
height: 6px;
background: inherit;
border-right: 1px solid rgba(255, 215, 0, 0.3);
border-bottom: 1px solid rgba(255, 215, 0, 0.3);
transform: rotate(45deg);
}
.progress-tooltip.visible {
opacity: 1;
}
.progress-info {
display: flex;
justify-content: space-between;
color: rgba(255, 215, 0, 0.8);
font-size: 0.7rem;
margin-top: 0.3rem;
}
.subscribe-text {
color: rgb(200, 200, 200);
font-size: 0.7rem;
margin-top: 0.3rem;
}
.loading .progress-bar {
background: linear-gradient(90deg,
rgba(255, 215, 0, 0.1),
rgba(255, 215, 0, 0.2)
);
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
const container = document.querySelector('.terminal-window');
const progressBar = container.querySelector('.progress-bar');
const progressPercent = container.querySelector('.progress-percent');
const tooltip = container.querySelector('.progress-tooltip');
let progress = 0;
let lastScrollTop = 0;
let scrollSensitivity = 5;
container.classList.add('loading');
function updateProgress(scrollDelta) {
const viewportHeight = window.innerHeight;
const docHeight = document.documentElement.scrollHeight - viewportHeight;
const increment = (Math.abs(scrollDelta) / docHeight) * 100 * scrollSensitivity;
progress = Math.min(75, progress + (increment * 0.8));
progressBar.style.width = `${progress}%`;
progressPercent.textContent = `${Math.round(progress)}%`;
if (progress >= 70) {
tooltip.classList.add('visible');
} else {
tooltip.classList.remove('visible');
}
if (progress > 0) {
container.classList.remove('loading');
}
}
window.addEventListener('scroll', () => {
const scrollTop = window.scrollY;
const scrollDelta = Math.abs(scrollTop - lastScrollTop);
lastScrollTop = scrollTop;
requestAnimationFrame(() => updateProgress(scrollDelta));
}, { passive: true });
window.addEventListener('wheel', (e) => {
const wheelDelta = Math.abs(e.deltaY);
requestAnimationFrame(() => updateProgress(wheelDelta / 5));
}, { passive: true });
});
</script>
<div class="terminal-window">
<div class="terminal-prompt">
> Building Change Maker V3...
</div>
<div class="progress-container">
<div class="progress-tooltip">
<span class="tooltip-line1">Testing with Partners now.</span>
<span class="tooltip-line2">Email for Opportunity.</span>
</div>
<div class="progress-bar"></div>
</div>
<div class="progress-info">
<span class="progress-percent">0%</</span>
<span>Target: Late November</span>
</div>
<div class="subscribe-text">
Subscribe to newsletter to get code delivered right to the inbox.
</div>
</div>
<div class="power-header">
<h1>Not a dime spent on advertising and you still heard of us?</h1>
</div>
<form method="post" action="https://listmonk.bnkops.com/subscription/form" class="listmonk-form">
<div class="form-content">
<!-- Orbiting Text Elements -->
<div class="orbit-text" style="--start-rotation: 0deg;">✨ Stay in the Loop ✨</div>
<div class="orbit-text" style="--start-rotation: 120deg;">✨ Subscribe for Code ✨</div>
<div class="orbit-text" style="--start-rotation: 240deg;">✨ Get the Latest ✨</div>
<!-- Form Inputs -->
<input type="hidden" name="nonce" />
<input type="email" name="email" required placeholder="E-mail" />
<input type="text" name="name" placeholder="Name (optional)" />
<label>
<input id="038eb" type="checkbox" name="l" checked value="038eb469-e141-435d-86eb-2ab4df20cf9c" />
Weekly Releases and Updates
</label>
<!-- Subscribe Button -->
<div class="subscribe-container">
<input type="submit" value="Subscribe" />
</div>
</div>
</form>
<div class="section">
<h2>Some Features</h2>
<div class="feature-grid">
<!-- Existing cards -->
<div class="feature-card">
<h3><span class="emoji-float">📱</span> Mobile-First Design</h3>
<p>Responsive layout for both frontend and backend that is optimized for all devices with touch-friendly navigation. Why not write instead of doom scroll? 🤔❤️🤳</p>
</div>
<div class="feature-card">
<h3><span class="emoji-float">🔍</span> Instant Search</h3>
<p>Built-in search with real-time suggestions and keyword highlighting. Get curious visitors instant answers to their questions 🤓🫡.</p>
</div>
<div class="feature-card">
<h3><span class="emoji-float">🎨</span> Accessibilty & Dark Mode Support</h3>
<p>Accessible reading by default & automatic dark/light theme switching based on user preferences ❤️👀</p>
</div>
<!-- New security-focused cards -->
<div class="feature-card">
<h3><span class="emoji-float">🏠</span> Self-Hosted Platform</h3>
<p>Run everything on your own hardware. No external dependencies or cloud services required. Complete control over your infrastructure and data. 💪</p>
</div>
<div class="feature-card">
<h3><span class="emoji-float">🔐</span> 100% Confidential</h3>
<p>Your content stays private and secure. No data sharing, tracking, or external connections. Perfect for sensitive campaign materials and strategic planning. 🤫</p>
</div>
<div class="feature-card">
<h3><span class="emoji-float">🌐</span> VPN Compatible</h3>
<p>Works seamlessly with VPNs and anonymity tools. Enhanced privacy and security for your entire team's communications. 🛡️</p>
</div>
<!-- Remaining existing cards -->
<div class="feature-card">
<h3><span class="emoji-float">🚀</span> Social Cards</h3>
<p>Automatic social media cards and SEO optimization for better sharing. Like, if thats your thing 🤭</p>
</div>
<div class="feature-card">
<h3><span class="emoji-float">📊</span> Analytics Ready</h3>
<p>Easy integration with analytics if you so choose. If you like to watch, that's your thing 😆</p>
</div>
<div class="feature-card">
<h3><span class="emoji-float">🔒</span> Privacy Focused</h3>
<p>No external requests, GDPR compliant, and cookie-free by default. Build a site offline entirely, if you so choose.🙈🙉🙊 </p>
</div>
</div>
</div>
<div class="power-header">
<h2>The Fastest Writing Platform Available</h2>
</div>
<p>This documentation editor lets you create and manage content using markdown and Obsidian-style features. View, edit, and generate your site <a href="https://changemaker.bnkops.com/Backend%20%26%20Editor/">entirely in plain text.</a> Write and serve your content faster then ever before.</p>
<div class="typewriter-container">
<div id="typewriter-text"></div>
</div>
<div class="feature-grid">
<!-- Simple Markdown Writing -->
<div class="feature-card">
<h3><span class="emoji-float">📝</span> Simple Markdown Writing</h3>
<p>Use <a href="https://changemaker.bnkops.com/Simple%20Markdown%20Guide/">Markdown</a> for easy content creation</p>
</div>
<!-- Obsidian Integration -->
<div class="feature-card">
<h3><span class="emoji-float">🔗</span> Obsidian Integration</h3>
<p>Open your docs folder in <a href="https://changemaker.bnkops.com/obsidian/">Obsidian</a> for enhanced features</p>
</div>
<!-- Real-time Preview -->
<div class="feature-card">
<h3><span class="emoji-float">👁️</span> Real-time Preview</h3>
<p>See your changes immediately with live preview</p>
</div>
<!-- Auto-updating Links -->
<div class="feature-card">
<h3><span class="emoji-float">🔄</span> Auto-updating Links</h3>
<p>Internal links are managed automatically</p>
</div>
<!-- Custom Landing Page -->
<div class="feature-card">
<h3><span class="emoji-float">🎨</span> Custom Landing Page</h3>
<p>Use <a href="https://changemaker.bnkops.com/Customizing%20Your%20Landing%20Page%20with%20LLMs%20%28Ai%29/">our LLM prompting guide</a> to create beautiful custom landing pages</p>
</div>
<!-- Blogger Ready -->
<div class="feature-card">
<h3><span class="emoji-float">📝</span> Blogger Ready</h3>
<p>Backend builder mkdcos-material offers powerful blogging features with built-in plugins and extensions for a seamless documentation experience</p>
</div>
</div>
<style>
@keyframes smokeGlow {
0% {
opacity: 0.1;
filter: blur(15px);
transform: scale(0.98) translate(0, 0);
}
33% {
opacity: 0.3;
filter: blur(12px);
transform: scale(1.01) translate(-2px, 2px);
}
66% {
opacity: 0.2;
filter: blur(18px);
transform: scale(1.02) translate(2px, -2px);
}
100% {
opacity: 0.1;
filter: blur(15px);
transform: scale(0.98) translate(0, 0);
}
}
@keyframes orbit {
from {
transform: translate(-50%, -50%) rotate(var(--start-rotation)) translateX(120px) rotate(calc(-1 * var(--start-rotation)));
}
to {
transform: translate(-50%, -50%) rotate(calc(360deg + var(--start-rotation))) translateX(120px) rotate(calc(-360deg - var(--start-rotation)));
}
}
.listmonk-form {
position: relative !important;
background: rgba(45, 27, 77, 0.7) !important;
padding: 40px !important;
width: 100% !important;
box-sizing: border-box !important;
margin: 40px 0 !important;
display: flex !important;
flex-wrap: wrap !important;
align-items: center !important;
justify-content: center !important;
gap: 15px !important;
border-radius: 12px !important;
border: 1px solid rgba(255, 255, 255, 0.15) !important;
z-index: 1 !important;
min-height: 300px !important;
}
.listmonk-form::before,
.listmonk-form::after {
content: '' !important;
position: absolute !important;
top: -20px !important;
left: -20px !important;
right: -20px !important;
bottom: -20px !important;
background: rgba(255, 255, 255, 0.15) !important;
border-radius: 20px !important;
z-index: -1 !important;
pointer-events: none !important;
}
.listmonk-form::before {
animation: smokeGlow 8s ease-in-out infinite !important;
}
.listmonk-form::after {
animation: smokeGlow 8s ease-in-out infinite reverse !important;
animation-delay: -4s !important;
background: rgba(255, 255, 255, 0.1) !important;
}
.form-content {
position: relative !important; /* Added for orbiting text positioning */
display: flex !important;
flex-wrap: wrap !important;
gap: 15px !important;
justify-content: center !important;
align-items: center !important;
max-width: 600px !important;
margin: 0 auto !important;
z-index: 2 !important;
}
.subscribe-container {
position: relative !important;
display: flex !important;
justify-content: center !important;
align-items: center !important;
z-index: 2 !important;
}
.listmonk-form input[type="email"],
.listmonk-form input[type="text"],
.listmonk-form label,
.subscribe-container {
position: relative !important;
z-index: 2 !important; /* Ensure inputs are above orbiting text */
}
.listmonk-form input[type="email"],
.listmonk-form input[type="text"] {
background-color: #6a1b9a !important; /* Solid purple background */
border: 2px solid rgba(255, 255, 255, 0.2) !important;
color: #FFFFFF !important; /* Brightened text color */
padding: 12px 15px !important;
border-radius: 6px !important;
font-size: 15px !important;
font-weight: bold !important; /* Increased font weight */
flex: 1 !important;
min-width: 150px !important;
max-width: 250px !important;
transition: all 0.3s ease !important;
}
.listmonk-form input[type="email"]::placeholder,
.listmonk-form input[type="text"]::placeholder {
color: rgba(255, 255, 255, 0.8) !important; /* Brighter placeholder text color */
}
.listmonk-form input[type="email"]:focus,
.listmonk-form input[type="text"]:focus {
border-color: rgba(255, 255, 255, 0.4) !important;
background-color: #7b1fa2 !important; /* Slightly lighter purple on focus */
color: #FFFFFF !important; /* Ensure text remains bright on focus */
outline: none !important;
}
.listmonk-form input[type="submit"] {
background-color: rgba(255, 255, 255, 0.9) !important;
color: #2d1b4d !important;
padding: 12px 25px !important;
border: none !important;
border-radius: 6px !important;
cursor: pointer !important;
font-weight: bold !important;
font-size: 16px !important;
transition: all 0.3s ease !important;
letter-spacing: 0.5px !important;
position: relative !important;
z-index: 2 !important;
}
.listmonk-form input[type="submit"]:hover {
transform: translateY(-2px) !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2) !important;
background-color: rgba(240, 240, 240, 0.9) !important;
}
.listmonk-form label {
color: rgba(255, 255, 255, 0.9) !important;
font-weight: normal !important;
font-size: 15px !important;
display: inline-flex !important;
align-items: center !important;
margin-right: 15px !important;
flex: 1 1 100% !important;
}
.listmonk-form input[type="checkbox"] {
margin-right: 8px !important;
accent-color: #ffffff !important;
}
.listmonk-form input::placeholder {
color: rgba(255, 255, 255, 0.5) !important;
}
.orbit-text {
position: absolute !important;
top: 50% !important;
left: 50% !important;
transform-origin: center !important;
margin: 0 !important;
color: #ffffff !important;
font-size: 14px !important; /* Further reduced font size */
font-weight: bold !important;
text-shadow: 0 2px 4px rgba(0,0,0,0.2) !important;
letter-spacing: 0.5px !important;
white-space: nowrap !important;
animation: orbit 12s linear infinite !important; /* Even faster orbit */
background: rgba(45, 27, 77, 0.5) !important;
padding: 4px 10px !important; /* Further reduced padding */
border-radius: 20px !important;
backdrop-filter: blur(5px) !important;
pointer-events: none !important;
z-index: 1 !important;
}
@keyframes orbit {
from {
transform: translate(-50%, -50%) rotate(var(--start-rotation)) translateX(100px) rotate(calc(-1 * var(--start-rotation))); /* Further reduced orbit radius */
}
to {
transform: translate(-50%, -50%) rotate(calc(360deg + var(--start-rotation))) translateX(100px) rotate(calc(-360deg - var(--start-rotation))); /* Further reduced orbit radius */
}
}
</style>
<form method="post" action="https://listmonk.bnkops.com/subscription/form" class="listmonk-form">
<div class="form-content">
<!-- Orbiting Text Elements -->
<div class="orbit-text" style="--start-rotation: 0deg;">✨ Stay in the Loop ✨</div>
<div class="orbit-text" style="--start-rotation: 120deg;">✨ Subscribe for Code ✨</div>
<div class="orbit-text" style="--start-rotation: 240deg;">✨ Get the Latest ✨</div>
<!-- Form Inputs -->
<input type="hidden" name="nonce" />
<input type="email" name="email" required placeholder="E-mail" />
<input type="text" name="name" placeholder="Name (optional)" />
<label>
<input id="038eb" type="checkbox" name="l" checked value="038eb469-e141-435d-86eb-2ab4df20cf9c" />
Weekly Releases and Updates
</label>
<!-- Subscribe Button -->
<div class="subscribe-container">
<input type="submit" value="Subscribe" />
</div>
</div>
</form>
<div class="section">
<h2>In Development</h2>
<p>bnkops is working on Change Maker V4 right now, which will also be free. Features coming include:</p>
<ul>
<li>DNS (domain) hosting services under bnkops.com</li>
<li>One click install script for public access</li>
<li>Expanded frontend editor with more standard markdown editing features and content management</li>
<li>Expanded mobile features, such as content uploading and improved ui</li>
<li>Options to install local newsletter, email targeter, automation systems, and database integrations</li>
<li> Meta properties for documentation for states like draft, publish, author, publication time, etc.
</ul>
</div>
</div>
<div class="section" style="padding: 1.25rem; background: linear-gradient(145deg, rgba(255, 215, 0, 0.02), rgba(255, 215, 0, 0.01)); position: relative; overflow: hidden;">
<!-- Shimmer effect overlay -->
<div style="position: absolute; top: 0; left: 0; width: 200%; height: 100%; background: linear-gradient(to right, transparent, rgba(255, 215, 0, 0.1), transparent);"></div>
<div style="position: relative; width: 100%; padding: 1.25rem; background: linear-gradient(145deg, rgba(255, 215, 0, 0.08), rgba(255, 215, 0, 0.04)); border-radius: 8px; border: 1px solid rgba(255, 215, 0, 0.1);">
<h3 style="text-align: center; font-size: 1.2rem !important; margin-bottom: 0.5rem !important; color: var(--bnk-yellow);">Share the Magic! ✨</h3>
<p style="text-align: center; margin-bottom: 1rem; font-size: 0.9rem; color: var(--bnk-text-dim);">Want to support bnkops change maker? Help spread the word!</p>
<div style="display: flex; justify-content: center; gap: 1rem; flex-wrap: wrap;">
<button onclick="navigator.clipboard.writeText('Have you seen https://changemaker.bnkops.com? A open-source, free, simple, and powerful website generator and server application for running digital campaigns.'); alert('Link copied!');"
style="flex: 1; min-width: 120px; text-align: center; background: var(--bnk-yellow); color: black; padding: 0.5rem 1rem; border-radius: 6px; border: none; cursor: pointer; font-size: 0.9rem; transition: transform 0.2s ease, box-shadow 0.2s ease;"
onmouseover="this.style.transform='translateY(-2px)'; this.style.boxShadow='0 4px 12px rgba(255, 215, 0, 0.3)'"
onmouseout="this.style.transform='none'; this.style.boxShadow='none'">
📋 Copy url and short introduction
</button>
</div>
</div>
</div>
<style>
@keyframes shimmer {
100% {
transform: translateX(50%);
}
}
}
</style>
</div>
<script>
// Define the two message arrays
const taglines = [
"Documentation meets democracy: Professional-grade tools with revolutionary simplicity.",
"Your campaign's command center: Powerful documentation that adapts as fast as you do.",
"Secure, simple, sovereign: Documentation built for campaigns that make change.",
"Where simplicity meets strategy: Professional documentation tools built for changemakers.",
"Take control of your narrative: Professional documentation that evolves with your campaign."
];
const messages = [
"The promise is: If you can type, you can make a site.",
"Create websites effortlessly and itteratively.",
"Your content, your control.",
"Welcome to the future of web creation!",
"Empower your ideas with simplicity."
];
// Setup for both typewriters
const typewriterElement = document.getElementById('typewriter-text');
const cursorElement = document.getElementById('cursor');
const taglineElement = document.querySelector('.typewriter-text');
const taglineCursor = document.querySelector('.cursor');
let messageIndex = 0;
let taglineIndex = 0;
let typewriterIndex = 0;
let taglineTypeIndex = 0;
let isDeleting = false;
let isTaglineDeleting = false;
function getTextWidth(text, element) {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const computedStyle = window.getComputedStyle(element);
context.font = `${computedStyle.fontSize} ${computedStyle.fontFamily}`;
return context.measureText(text).width;
}
function updateCursorPosition(textElement, cursorElement) {
const textNode = textElement.firstChild;
const range = document.createRange();
range.selectNodeContents(textElement);
const textWidth = range.getBoundingClientRect().width;
cursorElement.style.position = 'absolute';
cursorElement.style.left = `${textWidth}px`;
// Calculate vertical position based on text height
const textHeight = textElement.getBoundingClientRect().height;
const lineHeight = parseInt(window.getComputedStyle(textElement).lineHeight);
const lines = Math.floor(textHeight / lineHeight);
// Position cursor at the end of text, accounting for multiple lines
cursorElement.style.top = `${(lines - 1) * lineHeight}px`;
}
function typeTagline() {
const currentTagline = taglines[taglineIndex];
if (!isTaglineDeleting) {
if (taglineTypeIndex < currentTagline.length) {
taglineElement.textContent += currentTagline.charAt(taglineTypeIndex);
taglineTypeIndex++;
setTimeout(typeTagline, 50);
} else {
setTimeout(() => {
isTaglineDeleting = true;
typeTagline();
}, 3000);
}
} else {
if (taglineTypeIndex > 0) {
taglineElement.textContent = currentTagline.substring(0, taglineTypeIndex - 1);
taglineTypeIndex--;
setTimeout(typeTagline, 30);
} else {
isTaglineDeleting = false;
taglineIndex = (taglineIndex + 1) % taglines.length;
setTimeout(typeTagline, 500);
}
}
}
function typeWriter() {
const currentMessage = messages[messageIndex];
if (!isDeleting) {
if (typewriterIndex < currentMessage.length) {
typewriterElement.textContent += currentMessage.charAt(typewriterIndex);
typewriterIndex++;
setTimeout(typeWriter, 50);
} else {
setTimeout(() => {
isDeleting = true;
typeWriter();
}, 2000);
}
} else {
if (typewriterIndex > 0) {
typewriterElement.textContent = currentMessage.substring(0, typewriterIndex - 1);
typewriterIndex--;
setTimeout(typeWriter, 30);
} else {
isDeleting = false;
messageIndex = (messageIndex + 1) % messages.length;
setTimeout(typeWriter, 500);
}
}
}
// Start both typewriter effects with a delay
setTimeout(typeTagline, 1000);
setTimeout(typeWriter, 1000);
document.addEventListener('DOMContentLoaded', function() {
// Intersection Observer for scroll animations
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('reveal');
}
});
}, {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
});
// Observe all animated elements
document.querySelectorAll('h2, p, .feature-card, ul li, .section').forEach(el => {
observer.observe(el);
});
// Emoji hover animation
document.querySelectorAll('.emoji-float').forEach(emoji => {
emoji.addEventListener('mouseover', () => {
emoji.style.animation = 'none';
emoji.offsetHeight; // Trigger reflow
emoji.style.animation = 'float 3s ease-in-out infinite';
});
});
// Terminal animation sequence
const terminalMessages = document.querySelectorAll('.typing-effect');
function animateMessages(index) {
if (index >= terminalMessages.length) return;
setTimeout(() => {
terminalMessages[index].classList.add('active');
animateMessages(index + 1);
}, 1000);
}
animateMessages(0);
// Reset and repeat animation
setInterval(() => {
terminalMessages.forEach(msg => {
msg.classList.remove('active');
});
setTimeout(() => {
animateMessages(0);
}, 500);
}, 8000);
});
</script>
{% endblock %}
{% block tabs %}
{{ super() }}
{% endblock %}