Files
auto/index.html
T
ilia a7269366c9
CI / skip-ci-check (pull_request) Successful in 51s
CI / secret-scan (pull_request) Successful in 47s
CI / node-ci (pull_request) Successful in 56s
Replace tiny logo OG with 1200×630 social image.
2026-08-12 13:53:17 -04:00

695 lines
31 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>AutoBank — Stop doing by hand what a computer can do for you</title>
<meta
name="description"
content="Automation for small and medium businesses: invoicing, follow-ups, data entry, and reports that used to eat your week now run on their own. Free 15-minute call to find out what's worth automating."
/>
<meta property="og:title" content="AutoBank — Stop doing by hand what a computer can do for you" />
<meta
property="og:description"
content="Automation for small and medium businesses — the manual work you haven't gotten around to naming yet, fixed and running on its own."
/>
<meta property="og:type" content="website" />
<meta property="og:url" content="https://auto.levkin.ca/" />
<meta property="og:site_name" content="AutoBank" />
<meta property="og:image" content="https://auto.levkin.ca/og-image.png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="AutoBank — Stop doing by hand what a computer can do for you" />
<meta
name="twitter:description"
content="Automation for small and medium businesses — invoicing, follow-ups, data entry, and reports, fixed and running on their own."
/>
<meta name="twitter:image" content="https://auto.levkin.ca/og-image.png" />
<link rel="canonical" href="https://auto.levkin.ca/" />
<link
rel="icon"
href="assets/logos/00-full-64.png"
type="image/png"
/>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "ProfessionalService",
"name": "AutoBank",
"url": "https://auto.levkin.ca/",
"description": "Automation for small and medium businesses: invoicing, follow-ups, data entry, and reporting, built and handed over running on their own.",
"email": "ilia@levkine.ca",
"areaServed": "North America",
"sameAs": [
"https://levkin.ca/",
"https://caseware.levkin.ca/",
"https://iliadobkin.com/",
"https://www.linkedin.com/in/ilia-dobkin-8263343/"
]
}
</script>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="styles.css" />
<script defer src="https://stats.levkin.ca/script.js" data-website-id="49c33962-d5f5-42ad-a74a-d0bda2d16f04"></script>
</head>
<body>
<a href="#main" class="skip-link">Skip to content</a>
<header class="site-header">
<div class="container header-inner">
<a href="#top" class="brand" aria-label="AutoBank — Home">
<span class="brand-mark-wrap" aria-hidden="true">
<img
class="brand-mark"
id="brand-logo"
src="assets/logos/00-full-64.png"
width="40"
height="40"
alt=""
/>
</span>
<span class="brand-text">
<span class="brand-name">AutoBank</span>
</span>
</a>
<div class="header-nav">
<button
type="button"
class="nav-toggle"
aria-expanded="false"
aria-controls="primary-nav"
>
<span class="nav-toggle-icon" aria-hidden="true"></span>
<span class="visually-hidden">Menu</span>
</button>
<nav id="primary-nav" class="primary-nav" aria-label="Primary">
<a href="#services">Services</a>
<a href="#process">Process</a>
<a href="#why">Why me</a>
<a href="https://cal.levkin.ca/ilia/consult" class="nav-cta" target="_blank" rel="noopener"
>Book a call<span class="visually-hidden"> (opens in new tab)</span></a
>
</nav>
</div>
</div>
</header>
<main id="main">
<!-- HERO -->
<section id="top" class="hero">
<div class="hero-bg" aria-hidden="true">
<div class="grid-bg"></div>
<div class="glow glow-1"></div>
<div class="glow glow-2"></div>
</div>
<div class="container hero-inner">
<div class="hero-eyebrow">
<span class="pulse"></span>
<span>Currently taking on new automation projects</span>
</div>
<h1 class="hero-title">
Stop doing by hand<br />
what a computer can do for you.
<span class="cursor" aria-hidden="true"></span>
</h1>
<p class="hero-lede">
Most business owners don't wake up thinking "I need automation" — they just know invoices slip through
the cracks, leads go cold, and end-of-month reports eat a whole day. That's the problem I fix: I find
the manual work costing you the most time and build something that does it for you, quietly, every day.
</p>
<div class="hero-cta-row">
<a href="https://cal.levkin.ca/ilia/consult" class="btn btn-primary" target="_blank" rel="noopener">
Book a free 15-min call<span class="visually-hidden"> (opens in new tab)</span>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
<path d="M3 8h10M9 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</a>
<a href="#examples" class="btn btn-ghost">See examples</a>
</div>
<!-- Terminal-ish window -->
<div class="terminal" aria-hidden="true">
<div class="terminal-bar">
<span class="dot red"></span>
<span class="dot yellow"></span>
<span class="dot green"></span>
<span class="terminal-title">~/your-business — autobank.sh</span>
</div>
<pre class="terminal-body"><span class="prompt">&gt;</span> <span class="cmd">RUN AUTO_PIPELINE target=your-business</span>
<span class="muted">[before] Invoices tracked by memory. Follow-ups when someone remembers.</span>
<span class="muted">[after] <span class="hl">Invoice → reminder → payment logged.</span> No one touches a keyboard.</span>
<span class="muted">[sys] Runs on schedule. No login required to check it worked.</span>
<span class="ok">[PASS] 14 manual steps eliminated</span>
<span class="ok">[PASS] Avg turnaround: 8 hrs → 90 sec</span>
<span class="ok">[PASS] Production ready · monitored · documented</span>
<span class="prompt blink">&gt;</span></pre>
</div>
</div>
</section>
<!-- SOUND FAMILIAR -->
<section id="familiar" class="section">
<div class="container">
<div class="section-head">
<p class="kicker">Sound familiar?</p>
<h2>You don't need to know the word for it. You just need it fixed.</h2>
</div>
<div class="familiar-grid">
<div class="familiar-card">
<p class="familiar-before"><span class="familiar-label">Before</span> Invoices get chased by memory and a spreadsheet, so some slip past due.</p>
<p class="familiar-after"><span class="familiar-label">After</span> Reminders go out on schedule. Payments get logged the moment they land.</p>
</div>
<div class="familiar-card">
<p class="familiar-before"><span class="familiar-label">Before</span> The same customer details get typed into three different systems by hand.</p>
<p class="familiar-after"><span class="familiar-label">After</span> One entry updates every system it needs to. No re-typing, no copy-paste drift.</p>
</div>
<div class="familiar-card">
<p class="familiar-before"><span class="familiar-label">Before</span> New leads sit for a day or two before anyone has time to follow up, and some go cold.</p>
<p class="familiar-after"><span class="familiar-label">After</span> Every new lead gets a personal-sounding reply within minutes, day or night.</p>
</div>
<div class="familiar-card">
<p class="familiar-before"><span class="familiar-label">Before</span> End-of-month numbers take a full day to pull together from three different tools.</p>
<p class="familiar-after"><span class="familiar-label">After</span> A finished report lands in your inbox before you're at your desk.</p>
</div>
</div>
</div>
</section>
<!-- LOGOS / PROOF STRIP -->
<section class="strip" aria-label="Tools I work with">
<div class="container">
<p class="strip-label">Tools I work with</p>
<ul class="strip-list">
<li>n8n</li>
<li>Zapier</li>
<li>Make</li>
<li>GitHub Actions</li>
<li>OpenAI</li>
<li>Claude</li>
<li>Webhooks</li>
<li>Shortcuts</li>
<li>Python · Node · Bash</li>
</ul>
</div>
</section>
<!-- SERVICES -->
<section id="services" class="section">
<div class="container">
<div class="section-head">
<p class="kicker">What I build</p>
<h2>From a small script that saves an hour a day,<br />to full pipelines that run your operations.</h2>
</div>
<div class="service-grid">
<article class="service-card">
<div class="service-icon">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6">
<rect x="3" y="3" width="18" height="18" rx="3" />
<path d="M8 9h8M8 13h8M8 17h5" stroke-linecap="round" />
</svg>
</div>
<h3>Custom scripts &amp; CLI tools</h3>
<p>Python, Node, and Bash automations that take a repetitive task and reduce it to one command — or zero.</p>
</article>
<article class="service-card">
<div class="service-icon">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6">
<circle cx="6" cy="6" r="2.5" />
<circle cx="18" cy="6" r="2.5" />
<circle cx="6" cy="18" r="2.5" />
<circle cx="18" cy="18" r="2.5" />
<path d="M8.5 6h7M6 8.5v7M18 8.5v7M8.5 18h7" stroke-linecap="round" />
</svg>
</div>
<h3>n8n, Zapier &amp; Make workflows</h3>
<p>No-code workflows that connect the tools you already use — Gmail, Slack, Notion, HubSpot, Stripe, Sheets, and 500+ more.</p>
</article>
<article class="service-card">
<div class="service-icon">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6">
<path d="M4 6h16M4 12h16M4 18h16" stroke-linecap="round" />
<circle cx="8" cy="6" r="2" fill="currentColor" stroke="none" />
<circle cx="16" cy="12" r="2" fill="currentColor" stroke="none" />
<circle cx="10" cy="18" r="2" fill="currentColor" stroke="none" />
</svg>
</div>
<h3>CI/CD pipelines</h3>
<p>GitHub Actions, Jenkins, Azure DevOps. Build, test, and deployment pipelines that turn manual hours into automated minutes.</p>
</article>
<article class="service-card">
<div class="service-icon">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6">
<path d="M12 3v6M12 15v6M3 12h6M15 12h6" stroke-linecap="round" />
<circle cx="12" cy="12" r="3" />
</svg>
</div>
<h3>Webhooks &amp; triggers</h3>
<p>Event-driven systems that react in real time — form submissions, payments, support tickets, file uploads, anything with an API.</p>
</article>
<article class="service-card">
<div class="service-icon">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6">
<path d="M12 2l2.4 5.6L20 9l-4 4 1 6-5-3-5 3 1-6-4-4 5.6-1.4z" stroke-linejoin="round" />
</svg>
</div>
<h3>AI &amp; LLM integrations</h3>
<p>Drop GPT, Claude, or local models into real workflows — summarize email, triage tickets, extract data, draft replies, generate reports.</p>
</article>
<article class="service-card">
<div class="service-icon">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6">
<circle cx="12" cy="12" r="9" />
<path d="M12 7v5l3 2" stroke-linecap="round" />
</svg>
</div>
<h3>Scheduled jobs &amp; reports</h3>
<p>Daily digests, weekly KPIs, end-of-month reports — running on schedule, landing where your team already lives.</p>
</article>
<article class="service-card">
<div class="service-icon">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6">
<rect x="5" y="2" width="14" height="20" rx="3" />
<path d="M10 18h4" stroke-linecap="round" />
</svg>
</div>
<h3>macOS &amp; iOS Shortcuts</h3>
<p>Personal productivity automations — one tap to capture, route, summarize, or trigger workflows from your phone or Mac.</p>
</article>
<article class="service-card">
<div class="service-icon">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6">
<path d="M4 4l16 8-16 8 4-8z" stroke-linejoin="round" />
</svg>
</div>
<h3>Custom integrations</h3>
<p>When off-the-shelf connectors don't cut it — custom APIs, OAuth flows, and bridges between systems that weren't meant to talk.</p>
</article>
</div>
<p class="services-footnote">
Don't see your use case? Most automation problems look unique until you describe them out loud.
<a href="https://cal.levkin.ca/ilia/consult" target="_blank" rel="noopener"
>Tell me what you're stuck on.<span class="visually-hidden"> (opens in new tab)</span></a
>
</p>
</div>
</section>
<!-- OUTCOMES BAND -->
<section class="outcomes" aria-label="Key outcomes">
<div class="container outcomes-inner">
<div class="outcome">
<div class="outcome-num">10×</div>
<div class="outcome-label">faster workflows than manual</div>
</div>
<div class="outcome">
<div class="outcome-num">24/7</div>
<div class="outcome-label">runs without you watching it</div>
</div>
<div class="outcome">
<div class="outcome-num">0</div>
<div class="outcome-label">copy-paste errors at 2&nbsp;a.m.</div>
</div>
</div>
</section>
<!-- PROCESS -->
<section id="process" class="section section-alt">
<div class="container">
<div class="section-head">
<p class="kicker">How it works</p>
<h2>Four steps. Production-ready at the end of them.</h2>
</div>
<ol class="process-list">
<li class="process-step">
<div class="step-num">01</div>
<div>
<h3>Discover</h3>
<p>Free 15-min call. You describe the painful part of your workflow. I tell you whether automation makes sense — honestly.</p>
</div>
</li>
<li class="process-step">
<div class="step-num">02</div>
<div>
<h3>Design</h3>
<p>A short proposal: what gets automated, which tools, how long it'll take, what it costs. No surprises.</p>
</div>
</li>
<li class="process-step">
<div class="step-num">03</div>
<div>
<h3>Ship</h3>
<p>I build it, test it, document it, and walk you through it. Production-ready means it survives bad data, retries, and a Monday morning.</p>
</div>
</li>
<li class="process-step">
<div class="step-num">04</div>
<div>
<h3>Maintain</h3>
<p>Optional ongoing support — monitoring, tweaks, and new automations as your business grows.</p>
</div>
</li>
</ol>
</div>
</section>
<!-- USE CASES -->
<section id="examples" class="section">
<div class="container">
<div class="section-head">
<p class="kicker">Examples</p>
<h2>Things teams hire me to automate.</h2>
</div>
<div class="usecase-grid">
<div class="usecase">
<span class="usecase-tag">Sales</span>
<p>New lead arrives → enriched in Clearbit/Apollo → scored → routed to the right rep on Slack → logged in CRM. All in seconds.</p>
</div>
<div class="usecase">
<span class="usecase-tag">Support</span>
<p>Incoming tickets summarized by an LLM, tagged by topic, severity-scored, and drafted with a suggested reply for an agent to send.</p>
</div>
<div class="usecase">
<span class="usecase-tag">Ops</span>
<p>End-of-day reports pulled from Stripe, Shopify, and Sheets — assembled into a single Slack digest at 6&nbsp;p.m. sharp.</p>
</div>
<div class="usecase">
<span class="usecase-tag">Marketing</span>
<p>Blog post published → auto-generate social copy → schedule across LinkedIn, X, and Bluesky → log performance back into Notion.</p>
</div>
<div class="usecase">
<span class="usecase-tag">Engineering</span>
<p>Pull request opened → tests run → preview deployed → screenshots posted as a comment → Slack notified. Faster reviews, fewer regressions.</p>
</div>
<div class="usecase">
<span class="usecase-tag">Personal</span>
<p>One Shortcut on your phone: captures voice → transcribes → routes to the right project in your Notion or Things inbox.</p>
</div>
</div>
</div>
</section>
<!-- WHY ME -->
<section id="why" class="section section-alt">
<div class="container">
<div class="why-grid">
<div>
<p class="kicker">Why me</p>
<h2>15+ years building automation that has to work.</h2>
<p class="why-lede">
I come from a software engineering background — JavaScript, .NET, CI/CD pipelines, and large enterprise
products where automation isn't a nice-to-have, it's how releases ship at all. That same engineering
discipline is what I bring to your business automation.
</p>
<ul class="why-list">
<li><strong>Production-ready by default.</strong> Error handling, retries, alerts, logs — not a happy-path demo.</li>
<li><strong>Documented.</strong> You shouldn't need me to understand what's running.</li>
<li><strong>Tested.</strong> Before it touches your live data.</li>
<li><strong>Pragmatic.</strong> A 20-line script often beats a 200-node workflow. I'll tell you which one you need.</li>
</ul>
</div>
<aside class="why-card">
<p class="why-card-eyebrow">Signature outcome</p>
<p class="why-card-stat">8 hrs → &lt; 2 min</p>
<p class="why-card-desc">
Release pipeline I built for an enterprise client — turning a multi-hour manual ritual into a
fully scripted, hands-off process. The same approach scales down to a small business saving an
hour a day on quote follow-ups.
</p>
</aside>
</div>
</div>
</section>
<!-- FAQ -->
<section class="section">
<div class="container">
<div class="section-head">
<p class="kicker">FAQ</p>
<h2>Common questions.</h2>
</div>
<div class="faq">
<details>
<summary>I don't know what to call my problem, is that OK?</summary>
<p>That's how most projects start. Describe what's eating your time in your own words — "I spend Fridays copying numbers into a spreadsheet" is plenty. Figuring out the fix, and what to call it, is my job.</p>
</details>
<details>
<summary>How much does a typical automation cost?</summary>
<p>Most projects land between a quick fixed-fee script and a multi-week build. I quote per project after the discovery call — no hourly billing surprises.</p>
</details>
<details>
<summary>Do I need to use a specific tool?</summary>
<p>No. I pick the right tool for the job — sometimes it's n8n, sometimes Zapier, sometimes a custom script. I'll explain the tradeoffs in plain language.</p>
</details>
<details>
<summary>What if I'm not sure automation is worth it?</summary>
<p>That's exactly what the free 15-min call is for. If automating a process won't pay back the cost of building it, I'll tell you.</p>
</details>
<details>
<summary>Do you work with companies outside Canada?</summary>
<p>Yes — fully remote, comfortable across North American and European time zones.</p>
</details>
<details>
<summary>Can you maintain what you build?</summary>
<p>Optional. I can hand it off with documentation, or stay on for monitoring and ongoing improvements.</p>
</details>
</div>
</div>
</section>
<!-- BOOK / CTA -->
<section id="book" class="cta-section">
<div class="cta-bg" aria-hidden="true">
<div class="grid-bg"></div>
<div class="glow glow-3"></div>
</div>
<div class="container cta-inner">
<p class="kicker kicker-light">Let's talk</p>
<h2>Book a free 15-minute consultation.</h2>
<p class="cta-lede">
Tell me about the part of your business that drains the most time. I'll tell you whether it's
worth automating — and if it is, exactly how I'd do it.
</p>
<div class="cta-row">
<a class="btn btn-primary btn-large" href="https://cal.levkin.ca/ilia/consult" target="_blank" rel="noopener">
Pick a time — 15 min free<span class="visually-hidden"> (opens in new tab)</span>
</a>
<a class="btn btn-ghost btn-large" href="mailto:ilia@levkine.ca?subject=Automation%20consultation%20(15%20min)&body=Hi%20Ilia%2C%0A%0AI%27d%20like%20to%20book%20a%2015-min%20consultation.%20Here%27s%20what%20I%27m%20looking%20to%20automate%3A%0A%0A">
Or email instead
</a>
</div>
<p class="cta-foot">No commitment. No sales pitch. Just a conversation.</p>
</div>
</section>
<!-- EMAIL CAPTURE (for visitors not ready to book) -->
<section id="subscribe" class="subscribe-section" aria-label="Subscribe for automation ideas">
<div class="container subscribe-inner">
<p class="subscribe-lede">Not ready to book a call? Get one short automation idea a month — no pitch, just something you could hand to whoever runs your ops.</p>
<form
id="subscribe-form"
class="subscribe-form"
action="https://listmonk.levkin.ca/subscription/form"
method="POST"
target="_blank"
>
<label class="visually-hidden" for="subscribe-email">Email address</label>
<input
id="subscribe-email"
type="email"
name="email"
placeholder="you@yourbusiness.com"
required
/>
<!-- List: "auto.levkin.ca leads" (public, single opt-in) in Listmonk. -->
<input type="hidden" name="l" value="84422fe9-61df-4bcd-8b2b-65a335a9a141" />
<button type="submit" class="btn btn-ghost">Subscribe</button>
</form>
<p id="subscribe-status" class="subscribe-status" role="status" aria-live="polite"></p>
</div>
</section>
</main>
<footer class="site-footer">
<div class="container footer-inner">
<p>© <span id="year"></span> AutoBank · Ilia Dobkin</p>
<p class="footer-meta">
<a href="mailto:ilia@levkine.ca">ilia@levkine.ca</a>
·
<a href="https://www.linkedin.com/in/ilia-dobkin-8263343/" target="_blank" rel="noopener"
>LinkedIn<span class="visually-hidden"> (opens in new tab)</span></a
>
·
<a href="https://git.levkin.ca" target="_blank" rel="noopener"
>git.levkin.ca<span class="visually-hidden"> (opens in new tab)</span></a
>
</p>
</div>
</footer>
<script>
document.getElementById("year").textContent = new Date().getFullYear();
const subscribeForm = document.getElementById("subscribe-form");
const subscribeStatus = document.getElementById("subscribe-status");
if (subscribeForm && subscribeStatus) {
subscribeForm.addEventListener("submit", async (e) => {
e.preventDefault();
const email = document.getElementById("subscribe-email").value.trim();
const listUuid = subscribeForm.querySelector('input[name="l"]').value;
const submitBtn = subscribeForm.querySelector('button[type="submit"]');
if (!email) return;
submitBtn.disabled = true;
subscribeStatus.textContent = "Sending…";
try {
const res = await fetch("https://listmonk.levkin.ca/api/public/subscription", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, list_uuids: [listUuid] }),
});
if (!res.ok) throw new Error(`Subscribe failed (${res.status})`);
const data = await res.json().catch(() => ({}));
subscribeStatus.textContent = data?.data?.has_optin
? "Check your email to confirm the subscription."
: "Subscribed. First idea lands next month.";
subscribeForm.reset();
} catch (err) {
subscribeStatus.textContent = "Something went wrong. Email ilia@levkine.ca instead and I'll add you by hand.";
} finally {
submitBtn.disabled = false;
}
});
}
const navToggle = document.querySelector(".nav-toggle");
const primaryNav = document.getElementById("primary-nav");
function setNavOpen(open) {
if (!navToggle || !primaryNav) return;
navToggle.setAttribute("aria-expanded", String(open));
primaryNav.classList.toggle("is-open", open);
}
if (navToggle && primaryNav) {
navToggle.addEventListener("click", () => {
setNavOpen(navToggle.getAttribute("aria-expanded") !== "true");
});
primaryNav.querySelectorAll("a").forEach((link) => {
link.addEventListener("click", () => setNavOpen(false));
});
document.addEventListener("keydown", (e) => {
if (e.key === "Escape") setNavOpen(false);
});
}
const LOGO_FRAMES = [
"assets/logos/00-full-64.png",
"assets/logos/01-25pct-64.png",
"assets/logos/02-15pct-64.png",
"assets/logos/03-3grains-64.png",
"assets/logos/04-1grain-64.png",
];
LOGO_FRAMES.forEach((src) => {
const img = new Image();
img.src = src;
});
const brandLogo = document.getElementById("brand-logo");
const motionQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
let prefersReducedMotion = motionQuery.matches;
motionQuery.addEventListener("change", (e) => {
prefersReducedMotion = e.matches;
});
function logoIndexFromScroll() {
const doc = document.documentElement;
const max = doc.scrollHeight - window.innerHeight;
if (max <= 0) return 0;
const progress = Math.min(1, Math.max(0, window.scrollY / max));
return Math.min(LOGO_FRAMES.length - 1, Math.floor(progress * LOGO_FRAMES.length));
}
let logoTicking = false;
function updateBrandLogo() {
if (!brandLogo || prefersReducedMotion) return;
const idx = logoIndexFromScroll();
const next = LOGO_FRAMES[idx];
if (brandLogo.getAttribute("src") === next) return;
brandLogo.src = next;
}
function onScrollFrame() {
updateBrandLogo();
logoTicking = false;
}
const header = document.querySelector(".site-header");
const onScroll = () => {
header.classList.toggle("is-scrolled", window.scrollY > 8);
if (!logoTicking) {
logoTicking = true;
requestAnimationFrame(onScrollFrame);
}
};
onScroll();
updateBrandLogo();
window.addEventListener("scroll", onScroll, { passive: true });
window.addEventListener("resize", () => {
updateBrandLogo();
}, { passive: true });
if ("IntersectionObserver" in window && !prefersReducedMotion) {
document.documentElement.classList.add("js-reveal");
const targets = document.querySelectorAll(
".section, .hero-inner, .service-card, .process-step, .usecase, .why-grid, .terminal"
);
const io = new IntersectionObserver(
(entries) => {
entries.forEach((e) => {
if (e.isIntersecting) {
e.target.classList.add("is-in");
io.unobserve(e.target);
}
});
},
{ threshold: 0.08, rootMargin: "0px 0px -40px 0px" }
);
targets.forEach((el) => {
el.classList.add("reveal");
io.observe(el);
});
setTimeout(() => {
targets.forEach((el) => el.classList.add("is-in"));
}, 1500);
}
</script>
</body>
</html>