feat(server): build axum web server for licensing, landing page, and updates

This commit is contained in:
Stevan Freeborn
2026-07-23 11:59:38 -05:00
parent 3b873f41a7
commit 792e6bd859
40 changed files with 3526 additions and 0 deletions
+83
View File
@@ -0,0 +1,83 @@
{% extends "base.html" %}
{% block title %}Page Not Found — CleanCopy{% endblock %}
{% block head %}
<style>
.error-container {
text-align: center;
}
.error-icon {
font-size: 4rem;
margin-bottom: 1rem;
}
h1 {
font-size: 2rem;
margin-bottom: 1rem;
color: var(--color-accent);
}
.error-message {
background: var(--color-bg-elevated);
border: 1px solid var(--color-border-subtle);
border-radius: 8px;
padding: 1.5rem;
margin: 2rem auto;
text-align: left;
}
.error-message p {
margin-bottom: 0;
color: var(--color-text-primary);
}
.error-hint {
color: var(--color-text-secondary);
font-size: 0.9rem;
margin-top: 1.5rem;
}
.error-actions {
margin-top: 2rem;
}
.error-actions a {
display: inline-block;
padding: 0.75rem 1.5rem;
background: var(--color-accent);
color: var(--color-accent-text-on);
text-decoration: none;
border-radius: 8px;
font-weight: bold;
}
.error-actions a:hover {
background: var(--color-accent-hover);
text-decoration: none;
}
</style>
{% endblock %}
{% block content %}
<div class="error-container">
<div class="error-icon"></div>
<h1>Page Not Found</h1>
<div class="error-message">
<p>
This page has been cleaned from existence. It was probably full of
tracking parameters.
</p>
</div>
<p class="error-hint">
The URL you visited doesn't exist, or may have been moved.
</p>
<div class="error-actions">
<a href="/">Back to Home</a>
</div>
</div>
{% endblock %}
+84
View File
@@ -0,0 +1,84 @@
{% extends "base.html" %}
{% block title %}Something Went Wrong — CleanCopy{% endblock %}
{% block head %}
<style>
.error-container {
text-align: center;
}
.error-icon {
font-size: 4rem;
margin-bottom: 1rem;
}
h1 {
font-size: 2rem;
margin-bottom: 1rem;
color: var(--color-error);
}
.error-message {
background: var(--color-bg-elevated);
border: 1px solid var(--color-border-subtle);
border-radius: 8px;
padding: 1.5rem;
margin: 2rem auto;
text-align: left;
}
.error-message p {
margin-bottom: 0;
color: var(--color-text-primary);
}
.error-hint {
color: var(--color-text-secondary);
font-size: 0.9rem;
margin-top: 1.5rem;
}
.error-actions {
margin-top: 2rem;
}
.error-actions a {
display: inline-block;
padding: 0.75rem 1.5rem;
background: var(--color-accent);
color: var(--color-accent-text-on);
text-decoration: none;
border-radius: 8px;
font-weight: bold;
}
.error-actions a:hover {
background: var(--color-accent-hover);
text-decoration: none;
}
</style>
{% endblock %}
{% block content %}
<div class="error-container">
<div class="error-icon"></div>
<h1>Something Went Wrong</h1>
<div class="error-message">
<p>
Our clipboard cleaner hit an unexpected bump. This has been logged
and we're looking into it.
</p>
</div>
<p class="error-hint">
If this keeps happening, please
<a href="mailto:{{ email }}">contact support</a>.
</p>
<div class="error-actions">
<a href="/">Back to Home</a>
</div>
</div>
{% endblock %}
+184
View File
@@ -0,0 +1,184 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" type="image/png" href="/static/favicon.png" />
<title>{% block title %}CleanCopy{% endblock %}</title>
<style>
@font-face {
font-family: "CascadiaCode";
src: url("/static/fonts/CaskaydiaCoveNerdFont-Regular.ttf") format("truetype");
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: "CascadiaCode";
src: url("/static/fonts/CaskaydiaCoveNerdFont-Bold.ttf") format("truetype");
font-weight: bold;
font-style: normal;
}
:root {
--color-bg-base: #1c2128;
--color-bg-elevated: #22272e;
--color-border-subtle: #2d333b;
--color-border-muted: #444c56;
--color-text-primary: #adbac7;
--color-text-secondary: #768390;
--color-text-emphasis: #cdd9e5;
--color-accent: #b39cd0;
--color-accent-hover: rgba(179, 156, 208, 0.85);
--color-accent-text-on: #1c2128;
--color-success: #4ade80;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body,
.container {
height: 100%;
}
body {
display: flex;
flex-direction: column;
font-family: "CascadiaCode", monospace;
background: var(--color-bg-base);
color: var(--color-text-primary);
line-height: 1.7;
}
.container {
display: flex;
flex-direction: column;
max-width: 720px;
margin: 0 auto;
padding: 2rem;
padding-bottom: 0;
}
main {
flex: 1;
}
h1 {
font-size: 2rem;
margin-bottom: 0.5rem;
color: var(--color-accent);
}
h2 {
font-size: 1.2rem;
margin-top: 2rem;
margin-bottom: 0.5rem;
color: var(--color-accent);
}
p {
margin-bottom: 1rem;
}
ul,
ol {
margin-bottom: 1rem;
}
ul {
padding-left: 1.5rem;
}
ol {
padding-left: 2.5rem;
}
li {
margin-bottom: 0.4rem;
}
a {
color: var(--color-accent);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.back {
display: inline-block;
margin-bottom: 1.5rem;
}
.topnav {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 2rem;
padding-bottom: 1rem;
border-bottom: 1px solid var(--color-border-subtle);
}
.topnav-brand {
font-size: 1.1rem;
font-weight: bold;
color: var(--color-accent);
text-decoration: none;
}
.topnav-links a {
color: var(--color-text-primary);
text-decoration: none;
margin-left: 1.5rem;
font-size: 0.95rem;
}
.topnav-links a:hover {
color: var(--color-accent);
}
footer {
margin-top: 2rem;
padding: 1rem 0;
border-top: 1px solid var(--color-border-subtle);
color: var(--color-text-secondary);
font-size: 0.9rem;
}
footer a {
color: var(--color-accent);
text-decoration: none;
}
</style>
{% block head %}{% endblock %}
</head>
<body>
<div class="container">
<nav class="topnav">
<a href="/" class="topnav-brand">CleanCopy</a>
<div class="topnav-links">
<a href="/docs">Docs</a>
</div>
</nav>
<main>
{% block content %}{% endblock %}
</main>
<footer>
<div><a href="/terms">Terms</a> &middot; <a href="/refunds">Refunds</a> &middot; <a href="/privacy">Privacy</a></div>
<p>&copy; 2026 CleanCopy. All rights reserved.</p>
</footer>
</div>
<!-- Simple Analytics - 100% privacy-first analytics -->
<script async src="https://scripts.simpleanalyticscdn.com/latest.js"></script>
<noscript><img src="https://queue.simpleanalyticscdn.com/noscript.gif" alt="" referrerpolicy="no-referrer-when-downgrade" /></noscript>
</body>
</html>
+137
View File
@@ -0,0 +1,137 @@
{% extends "base.html" %}
{% block title %}Documentation — CleanCopy{% endblock %}
{% block head %}
<style>
code {
background: var(--color-border-subtle);
padding: 0.15rem 0.4rem;
border-radius: 4px;
font-size: 0.9rem;
}
kbd {
background: var(--color-border-subtle);
border: 1px solid var(--color-border-muted);
border-radius: 4px;
padding: 0.1rem 0.4rem;
font-size: 0.85rem;
font-family: inherit;
}
.section {
margin-bottom: 2.5rem;
}
</style>
{% endblock %}
{% block content %}
<a class="back" href="/">← Home</a>
<h1>CleanCopy Documentation</h1>
<div class="section">
<h2>What is CleanCopy?</h2>
<p>
CleanCopy is a lightweight clipboard cleaning tool for Windows. When
triggered, it instantly sanitizes the text currently in your clipboard
— stripping trackers, normalizing typography, and removing invisible
characters.
</p>
</div>
<div class="section">
<h2>Installation</h2>
<ol>
<li>
Complete your purchase on the
<a href="/">homepage</a>.
</li>
<li>
Check your receipt email for the download link and your payment ID.
</li>
<li>
Download and run the installer. CleanCopy will start automatically.
</li>
<li>The CleanCopy icon will appear in your system tray.</li>
</ol>
</div>
<div class="section">
<h2>How to Use</h2>
<p>
Copy text to your clipboard as usual. When you're ready to clean it:
</p>
<ol>
<li>
Press <kbd>Ctrl</kbd> + <kbd>C</kbd> twice quickly (default
shortcut).
</li>
<li>CleanCopy processes the clipboard text in place.</li>
<li>Paste the cleaned text wherever you need it.</li>
</ol>
<p>
That's it — there's no window to interact with. CleanCopy works
silently in the background.
</p>
</div>
<div class="section">
<h2>What Gets Cleaned</h2>
<ul>
<li>
<strong>Tracking parameters</strong> — Removes
<code>utm_source</code>, <code>utm_medium</code>,
<code>gclid</code>, <code>fbclid</code>, and other marketing
trackers from URLs while preserving functional query parameters.
</li>
<li>
<strong>Smart quotes &amp; dashes</strong> — Converts curly quotes
(<code>" "</code> <code>' '</code>) to straight quotes and
em/en-dashes to hyphens.
</li>
<li>
<strong>Line breaks</strong> — Joins single-newline wraps from chat
apps and emails into continuous lines, while preserving paragraph
breaks.
</li>
<li>
<strong>Invisible characters</strong> — Removes zero-width spaces,
null bytes, and other invisible Unicode characters.
</li>
</ul>
</div>
<div class="section">
<h2>Configuration</h2>
<p>
Open the settings window from the system tray icon or by pressing
<kbd>Ctrl</kbd> + <kbd>C</kbd> while no text is selected. From there
you can:
</p>
<ul>
<li>Toggle individual cleaning rules on or off.</li>
<li>Add custom URL tracking parameters to strip.</li>
<li>Change the activation shortcut.</li>
</ul>
</div>
<div class="section">
<h2>Troubleshooting</h2>
<ul>
<li>
<strong>Shortcut doesn't work</strong> — Another app may be using
the same shortcut. Try changing it in Settings.
</li>
<li>
<strong>CleanCopy won't start</strong> — Make sure it's not blocked
by your antivirus. Add it to your allowlist if needed.
</li>
<li>
<strong>License not activating</strong> — Ensure you have a stable
internet connection and that your payment ID (starting with
<code>pi_</code>) is correct.
</li>
</ul>
</div>
{% endblock %}
+143
View File
@@ -0,0 +1,143 @@
{% extends "base.html" %}
{% block title %}CleanCopy — Clipboard Cleaning for Windows{% endblock %}
{% block head %}
<style>
.container {
max-width: 800px;
}
.hero {
text-align: center;
margin-bottom: 2rem;
}
.hero-logo {
width: 128px;
height: 128px;
margin-bottom: 1rem;
}
.hero h1 {
font-size: 2.5rem;
margin-bottom: 0.5rem;
}
.hero .tagline {
font-size: 1.2rem;
color: var(--color-text-primary);
}
.features {
margin: 2rem 0;
}
.feature {
padding: 1rem 0;
border-bottom: 1px solid var(--color-border-subtle);
}
.feature:last-child {
border-bottom: none;
}
.feature h3 {
color: var(--color-accent);
margin-bottom: 0.25rem;
}
.pricing {
margin: 2.5rem 0;
text-align: center;
padding: 2rem;
background: var(--color-bg-elevated);
border: 1px solid var(--color-border-subtle);
border-radius: 12px;
}
.pricing .price {
font-size: 2.5rem;
font-weight: bold;
color: var(--color-accent);
}
.pricing .detail {
color: var(--color-text-primary);
margin-top: 0.5rem;
}
.cta {
margin: 2rem 0;
text-align: center;
}
.cta a {
display: inline-block;
padding: 1rem 2rem;
background: var(--color-accent);
color: var(--color-accent-text-on);
text-decoration: none;
border-radius: 8px;
font-weight: bold;
font-size: 1.1rem;
}
.cta a:hover {
background: var(--color-accent-hover);
}
</style>
{% endblock %}
{% block content %}
<div class="hero">
<img src="/static/logo.png" alt="CleanCopy" class="hero-logo" />
<h1>CleanCopy</h1>
<p class="tagline">
Lightweight clipboard cleaning for Windows. Silently sanitizes your
clipboard text on trigger.
</p>
</div>
<div class="pricing">
<div class="price">{{ price }}</div>
<div class="detail">
One-time purchase · Lifetime license · Unlimited devices
</div>
<div class="cta">
<a href="/api/checkout">Buy CleanCopy →</a>
</div>
</div>
<div class="features">
<div class="feature">
<h3>Tracking Parameter Stripper</h3>
<p>
Removes marketing trackers (utm_*, gclid, fbclid, etc.) from URLs
while keeping functional query arguments.
</p>
</div>
<div class="feature">
<h3>Smart Quotes &amp; Dash Fixer</h3>
<p>
Converts curly quotes and em/en-dashes to standard straight quotes
and hyphens.
</p>
</div>
<div class="feature">
<h3>Line-Break Normalizer</h3>
<p>
Joins single-newline wraps from chat apps into continuous lines
while preserving paragraphs.
</p>
</div>
<div class="feature">
<h3>Invisible Character Cleanup</h3>
<p>
Removes zero-width spaces, null bytes, and other invisible Unicode
characters.
</p>
</div>
</div>
{% endblock %}
+113
View File
@@ -0,0 +1,113 @@
{% extends "base.html" %}
{% block title %}Privacy Policy — CleanCopy{% endblock %}
{% block head %}
<style>
.updated {
color: var(--color-text-secondary);
font-size: 0.9rem;
margin-bottom: 2rem;
}
</style>
{% endblock %}
{% block content %}
<a class="back" href="/">← Home</a>
<h1>Privacy Policy</h1>
<p class="updated">Last updated: {{ date }}</p>
<h2>Overview</h2>
<p>
CleanCopy is a clipboard cleaning tool that runs entirely on your
Windows PC. We value your privacy and have designed both our website and
software to collect only what is necessary.
</p>
<h2>Website Analytics</h2>
<p>
This website uses
<a href="https://simpleanalytics.com" target="_blank">Simple Analytics</a>, a
privacy-friendly analytics service. Simple Analytics collects:
</p>
<ul>
<li>Page views and referrer information</li>
<li>Browser type and device type</li>
<li>Country-level geographic location (not precise location)</li>
</ul>
<p>
Simple Analytics does <strong>not</strong> use cookies, does not track
individual users across sites, and does not collect personal
information. No consent banner is required because no personal data is
collected. See the
<a href="https://simpleanalytics.com/privacy" target="_blank">Simple Analytics privacy
policy</a>
for details.
</p>
<h2>License Activation</h2>
<p>
When you activate CleanCopy, the app sends the following to our
activation server:
</p>
<ul>
<li>
<strong>Payment ID</strong> — the <code>pi_...</code> identifier from
your Stripe receipt email
</li>
<li>
<strong>Hardware ID (HWID)</strong> — a SHA-256 hash derived from your
Windows machine identifiers
</li>
</ul>
<p>
This data is used solely to verify your purchase and issue a signed
license token. The HWID is stored in the license token to prevent
license sharing. We do not collect your name, email address, IP address,
or any other personal information during activation.
</p>
<h2>License Storage</h2>
<p>
Your signed license token is stored locally on your device at
<code>&lt;app_config_dir&gt;/license.lic</code>. This file never leaves
your device. It is a digitally signed JSON payload containing your
payment ID, HWID, and license metadata.
</p>
<h2>Payments</h2>
<p>
All payment processing is handled by
<a href="https://stripe.com" target="_blank">Stripe</a>
as the merchant of record. CleanCopy never sees, stores, or has access
to your credit card number, bank details, or other payment credentials.
Stripe's own
<a href="https://stripe.com/privacy" target="_blank">privacy policy</a>
governs how your payment information is handled.
</p>
<h2>Data Sharing</h2>
<p>
We do not sell, trade, or share your data with third parties except as
described in this policy (Simple Analytics for website analytics, Stripe
for payment processing).
</p>
<h2>Cookies</h2>
<p>
This website does not use cookies. Simple Analytics operates without
cookies.
</p>
<h2>Changes to This Policy</h2>
<p>
We may update this Privacy Policy from time to time. Changes will be
reflected on this page with an updated date.
</p>
<h2>Contact</h2>
<p>
Questions about this Privacy Policy?
<a href="mailto:{{ email }}">Contact us</a>.
</p>
{% endblock %}
+76
View File
@@ -0,0 +1,76 @@
{% extends "base.html" %}
{% block title %}Refund Policy — CleanCopy{% endblock %}
{% block head %}
<style>
.updated {
color: var(--color-text-secondary);
font-size: 0.9rem;
margin-bottom: 2rem;
}
.highlight {
background: var(--color-bg-elevated);
border: 1px solid var(--color-border-subtle);
border-radius: 8px;
padding: 1rem 1.5rem;
margin: 1.5rem 0;
}
</style>
{% endblock %}
{% block content %}
<a class="back" href="/">← Home</a>
<h1>Refund Policy</h1>
<p class="updated">Last updated: {{ date }}</p>
<h2>30-Day Money-Back Guarantee</h2>
<p>
We want you to be satisfied with CleanCopy. If you're not happy with
your purchase, you can request a full refund within 30 days of your
purchase date.
</p>
<div class="highlight">
<strong>How to request a refund:</strong>
<p style="margin-top: 0.5rem; margin-bottom: 0">
Email
<a href="mailto:{{ email }}">{{ email }}</a> with
your payment ID (the <code>pi_...</code> value from your receipt
email) and a brief reason for the refund. We'll process it within 23
business days.
</p>
</div>
<h2>What happens after a refund</h2>
<ul>
<li>Your license will be deactivated on our servers.</li>
<li>
CleanCopy will stop working on your device after the next license
check.
</li>
<li>You must delete the software and all copies from your devices.</li>
</ul>
<h2>Exceptions</h2>
<p>Refunds may be denied in the following cases:</p>
<ul>
<li>Requests made more than 30 days after purchase.</li>
<li>Refund requests for the same purchase made previously.</li>
<li>Requests from users who have violated the Terms of Service.</li>
</ul>
<h2>Processing</h2>
<p>
Refunds are processed through Stripe to the original payment method.
Depending on your bank, it may take 510 business days for the refund to
appear on your statement.
</p>
<h2>Contact</h2>
<p>
Questions about refunds?
<a href="mailto:{{ email }}">Contact us</a>.
</p>
{% endblock %}
+186
View File
@@ -0,0 +1,186 @@
{% extends "base.html" %}
{% block title %}Payment Successful — CleanCopy{% endblock %}
{% block head %}
<style>
.success-container {
text-align: center;
}
h1 {
font-size: 2rem;
margin-bottom: 1rem;
color: var(--color-success);
}
.checkmark {
font-size: 4rem;
margin-bottom: 1rem;
}
.instructions {
text-align: left;
background: var(--color-bg-elevated);
border: 1px solid var(--color-border-subtle);
border-radius: 8px;
padding: 1.5rem;
margin: 2rem 0;
}
.instructions h3 {
color: var(--color-accent);
margin-bottom: 0.75rem;
}
.instructions ol {
padding-left: 1.25rem;
}
.instructions li {
margin-bottom: 0.5rem;
}
.instructions code {
background: var(--color-border-subtle);
padding: 0.15rem 0.4rem;
border-radius: 4px;
font-size: 0.9rem;
color: var(--color-accent);
}
.note {
background: var(--color-bg-elevated);
border: 1px solid var(--color-border-subtle);
border-radius: 8px;
padding: 1rem;
margin: 1.5rem 0;
font-size: 0.9rem;
color: var(--color-text-primary);
}
.note strong {
color: var(--color-text-emphasis);
}
.download {
text-align: center;
background: var(--color-bg-elevated);
border: 1px solid var(--color-border-subtle);
border-radius: 8px;
padding: 1.5rem;
margin: 2rem 0;
}
.download h3 {
color: var(--color-accent);
margin-bottom: 0.5rem;
}
.download .version {
color: var(--color-text-primary);
margin-bottom: 1rem;
}
.download .version strong {
color: var(--color-text-emphasis);
}
.download-options {
display: flex;
flex-direction: column;
gap: 0.75rem;
align-items: center;
}
.download-btn {
display: inline-flex;
flex-direction: column;
padding: 0.75rem 1.5rem;
background: var(--color-accent);
color: var(--color-accent-text-on);
text-decoration: none;
border-radius: 8px;
font-weight: bold;
min-width: 280px;
text-align: center;
}
.download-btn:hover {
background: var(--color-accent-hover);
}
.download-btn-secondary {
background: transparent;
color: var(--color-accent);
border: 1px solid var(--color-accent);
}
.download-btn-secondary:hover {
background: var(--color-bg-elevated);
border-color: var(--color-accent-hover);
}
.download-hint {
font-size: 0.8rem;
font-weight: normal;
opacity: 0.8;
margin-top: 0.25rem;
}
.download .placeholder {
color: var(--color-text-secondary);
}
</style>
{% endblock %}
{% block content %}
<div class="success-container">
<div class="checkmark"></div>
<h1>Payment Successful</h1>
<p>Thank you for purchasing CleanCopy!</p>
</div>
<div class="download">
<h3>Download CleanCopy</h3>
{% if has_download %}
<p class="version">Latest version: <strong>{{ download_version }}</strong></p>
<div class="download-options">
<a href="{{ exe_url }}" class="download-btn">
Download for Windows (.exe)
<span class="download-hint">Portable — no installation required</span>
</a>
{% if has_msi %}
<a href="{{ msi_url }}" class="download-btn download-btn-secondary">
Download Installer (.msi)
<span class="download-hint">Traditional Windows installer</span>
</a>
{% endif %}
</div>
{% else %}
<p class="placeholder">No releases available yet. Check back soon or contact support.</p>
{% endif %}
</div>
<div class="instructions">
<h3>How to activate your license</h3>
<ol>
<li>Open CleanCopy on your Windows PC</li>
<li>Go to the <strong>License</strong> tab</li>
<li>
Find the payment ID in your receipt email — it starts with
<code>pi_</code>
</li>
<li>Paste it into the license key field</li>
<li>Click <strong>Activate</strong></li>
</ol>
</div>
<div class="note">
<strong>Can't find your payment ID?</strong> Check your email inbox (and
spam folder) for the receipt from CleanCopy. The payment ID is in the
receipt subject line or body.
</div>
<p>Need help? <a href="mailto:{{ email }}">Contact support</a></p>
{% endblock %}
+136
View File
@@ -0,0 +1,136 @@
{% extends "base.html" %}
{% block title %}Terms of Service — CleanCopy{% endblock %}
{% block head %}
<style>
.updated {
color: var(--color-text-secondary);
font-size: 0.9rem;
margin-bottom: 2rem;
}
</style>
{% endblock %}
{% block content %}
<a class="back" href="/">← Home</a>
<h1>Terms of Service</h1>
<p class="updated">Last updated: {{ date }}</p>
<h2>1. Acceptance of Terms</h2>
<p>
By purchasing, downloading, or using CleanCopy ("the Software"), you
agree to be bound by these Terms of Service. If you do not agree, do not
use the Software.
</p>
<h2>2. License Grant</h2>
<p>
CleanCopy is licensed, not sold. Upon successful payment, you are
granted a non-exclusive, non-transferable, perpetual license to install
and use the Software on devices you own or control, for personal or
commercial purposes.
</p>
<h2>3. Usage Restrictions</h2>
<ul>
<li>You may not redistribute, sell, or sublicense the Software.</li>
<li>
You may not reverse engineer, decompile, or disassemble the Software.
</li>
<li>You may not use the Software for any unlawful purpose.</li>
<li>
You may not remove or alter any proprietary notices or labels on the
Software.
</li>
</ul>
<h2>4. Intellectual Property</h2>
<p>
The Software and all intellectual property rights therein are and remain
the exclusive property of CleanCopy. These Terms do not grant you any
rights to use CleanCopy's trademarks, logos, or other brand features.
</p>
<h2>5. Payment</h2>
<p>
CleanCopy is a one-time purchase. Payment is processed securely through
<a href="https://stripe.com" target="_blank">Stripe</a>, which
acts as the merchant of record for all transactions. This means:
</p>
<ul>
<li>
Stripe is the seller of record and is responsible for processing your
payment, handling disputes, and managing chargebacks.
</li>
<li>
CleanCopy never sees, stores, or has access to your credit card
number, bank details, or other payment credentials.
</li>
<li>
Stripe's own
<a href="https://stripe.com/legal/ssa" target="_blank">Stripe Services Agreement</a>
and
<a href="https://stripe.com/privacy" target="_blank">Privacy Policy</a>
govern how your payment information is collected and processed.
</li>
<li>
You are responsible for any taxes associated with your purchase.
Prices are in USD unless otherwise stated.
</li>
</ul>
<h2>6. Updates</h2>
<p>
We may release updates to the Software from time to time. Your license
includes access to updates for the version of CleanCopy you purchased.
We reserve the right to modify or discontinue features in future
versions.
</p>
<h2>7. Disclaimer of Warranty</h2>
<p>
The Software is provided "as is" without warranty of any kind, express
or implied, including but not limited to the warranties of
merchantability, fitness for a particular purpose, and noninfringement.
We do not warrant that the Software will be uninterrupted, error-free,
or free of harmful components.
</p>
<h2>8. Limitation of Liability</h2>
<p>
To the maximum extent permitted by law, CleanCopy shall not be liable
for any indirect, incidental, special, consequential, or punitive
damages, or any loss of profits or revenue, whether incurred directly or
indirectly, or any loss of data, use, goodwill, or other intangible
losses resulting from your use of the Software.
</p>
<h2>9. Termination</h2>
<p>
Your license is effective until terminated. We may terminate your
license at any time if you fail to comply with these Terms. Upon
termination, you must cease all use of the Software and destroy all
copies.
</p>
<h2>10. Governing Law</h2>
<p>
These Terms shall be governed by and construed in accordance with the
laws of the United States, without regard to conflict of law principles.
</p>
<h2>11. Changes to Terms</h2>
<p>
We reserve the right to update these Terms at any time. Continued use of
the Software after changes constitutes acceptance of the new Terms. We
will notify users of material changes through the Software or our
website.
</p>
<h2>12. Contact</h2>
<p>
Questions about these Terms?
<a href="mailto:{{ email }}">Contact us</a>.
</p>
{% endblock %}