-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
224 lines (220 loc) · 41.3 KB
/
Copy pathindex.html
File metadata and controls
224 lines (220 loc) · 41.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Calm Studio — Digital Downloads</title>
<meta name="description" content="A calm boutique studio selling handcrafted Notion templates, React webapps, PDFs, spreadsheets, and tiny desktop utilities. Instant download, lifetime updates.">
<meta name="keywords" content="Notion templates, React apps, digital downloads, productivity tools, spreadsheets, PDFs, desktop utilities">
<meta name="author" content="Calm Studio">
<meta name="robots" content="index, follow">
<link rel="canonical" href="https://your-domain.com/">
<meta property="og:type" content="website">
<meta property="og:url" content="https://your-domain.com/">
<meta property="og:title" content="Calm Studio — Digital Downloads">
<meta property="og:description" content="Digital tools, templates & apps — made simple. Handcrafted Notion templates, React webapps, PDFs, and spreadsheets. Instant download, lifetime updates.">
<meta property="og:image" content="https://your-domain.com/og-image.jpg">
<meta property="og:site_name" content="Calm Studio">
<meta property="og:locale" content="en_US">
<meta property="twitter:card" content="summary_large_image">
<meta property="twitter:url" content="https://your-domain.com/">
<meta property="twitter:title" content="Calm Studio — Digital Downloads">
<meta property="twitter:description" content="Digital tools, templates & apps — made simple. Handcrafted Notion templates, React webapps, PDFs, and spreadsheets. Instant download, lifetime updates.">
<meta property="twitter:image" content="https://your-domain.com/og-image.jpg">
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><defs><filter id=%22s%22 x=%22-15%%22 y=%22-15%%22 width=%22130%%22 height=%22130%%22><feDropShadow dx=%220%22 dy=%224%22 stdDeviation=%224%22 flood-color=%22%23000%22 flood-opacity=%220.15%22/></filter></defs><rect x=%2212%22 y=%2212%22 width=%2276%22 height=%2276%22 rx=%2220%22 fill=%22%236B8F71%22 filter=%22url(%23s)%22/></svg>">
<script type="application/ld+json">{"@context":"https://schema.org","@type":"WebSite","name":"Calm Studio","url":"https://your-domain.com/","description":"A calm boutique studio selling handcrafted Notion templates, React webapps, PDFs, spreadsheets, and tiny desktop utilities"}</script>
<script type="application/ld+json">{"@context":"https://schema.org","@type":"Organization","name":"Calm Studio","url":"https://your-domain.com/","logo":"https://your-domain.com/logo.png"}</script>
<script type="application/ld+json">{"@context":"https://schema.org","@type":"ItemList","itemListElement":[{"@type":"Product","position":1,"name":"Notion Business OS Template","description":"Complete workspace for clients, projects, tasks and finance tracking.","brand":{"@type":"Brand","name":"Calm Studio"},"offers":{"@type":"Offer","price":"19.00","priceCurrency":"USD","availability":"https://schema.org/InStock","url":"#shop"}},{"@type":"Product","position":2,"name":"Minimal Portfolio Webapp (React)","description":"Fast, accessible portfolio with CMS, blog, and contact form.","brand":{"@type":"Brand","name":"Calm Studio"},"offers":{"@type":"Offer","price":"49.00","priceCurrency":"USD","availability":"https://schema.org/InStock","url":"#shop"}},{"@type":"Product","position":3,"name":"Invoice Generator Spreadsheet","description":"Google Sheets + Excel template with auto-tax, branding, and PDF export.","brand":{"@type":"Brand","name":"Calm Studio"},"offers":{"@type":"Offer","price":"12.00","priceCurrency":"USD","availability":"https://schema.org/InStock","url":"#shop"}},{"@type":"Product","position":4,"name":"Photo Batch Resizer (.exe)","description":"Windows utility to resize, compress, and rename thousands of photos offline.","brand":{"@type":"Brand","name":"Calm Studio"},"offers":{"@type":"Offer","price":"29.00","priceCurrency":"USD","availability":"https://schema.org/InStock","url":"#shop"}},{"@type":"Product","position":5,"name":"SaaS Dashboard UI Kit","description":"Figma + HTML components for analytics, settings, and billing flows.","brand":{"@type":"Brand","name":"Calm Studio"},"offers":{"@type":"Offer","price":"24.00","priceCurrency":"USD","availability":"https://schema.org/InStock","url":"#shop"}},{"@type":"Product","position":6,"name":"Project Planner PDF Pack","description":"Printable 90-day planner, weekly reviews, and habit trackers.","brand":{"@type":"Brand","name":"Calm Studio"},"offers":{"@type":"Offer","price":"15.00","priceCurrency":"USD","availability":"https://schema.org/InStock","url":"#shop"}}]}</script>
<style>
.btn{padding:13px 22px;border-radius:12px;border:0;font-weight:600;font-size:15px;cursor:pointer;transition:.2s;display:inline-flex;align-items:center;gap:8px}
.btn-primary{background:var(--charcoal);color:white;box-shadow:0 4px 14px rgba(45,55,72,.18)}
.btn-primary:hover{transform:translateY(-1px);box-shadow:0 8px 20px rgba(45,55,72,.22)}
.hero{padding:88px 0 64px;text-align:center}
.hero h1{font-size:clamp(34px,6vw,56px);line-height:1.05;margin:0 0 18px;font-weight:800;letter-spacing:-.02em}
.hero p{font-size:clamp(16px,2.2vw,19px);color:var(--charcoal-2);max-width:680px;margin:0 auto 32px}
.hero-cta{display:flex;gap:12px;justify-content:center;flex-wrap:wrap}
section{padding:64px 0;position:relative}section[id]{scroll-margin-top:80px}
section:not(:last-child)::after{content:'';position:absolute;bottom:0;left:50%;transform:translateX(-50%);width:100%;max-width:1100px;height:1px;background:rgba(45,55,72,.08)}
.section-head{text-align:center;margin-bottom:36px}
.eyebrow{display:inline-block;padding:6px 12px;background:var(--mist);color:var(--sage-dark);border-radius:999px;font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;margin-bottom:12px}
.section-head h2{font-size:clamp(26px,4vw,36px);margin:0 0 10px;letter-spacing:-.01em}
.section-head p{color:var(--charcoal-2);max-width:560px;margin:0 auto}
.filters{display:flex;gap:8px;justify-content:center;flex-wrap:wrap;margin-bottom:32px}
.filter{padding:9px 16px;border-radius:999px;border:1px solid rgba(45,55,72,.1);background:white;color:var(--charcoal-2);font-size:14px;font-weight:500;cursor:pointer;transition:.2s}
.filter.active,.filter:hover{background:var(--sage-dark);color:white;border-color:var(--sage-dark)}
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:24px}
.card{background:white;border-radius:16px;overflow:hidden;box-shadow:var(--shadow);display:flex;flex-direction:column;transition:.25s;border:1px solid rgba(45,55,72,.06)}
.card:hover{transform:translateY(-4px);box-shadow:0 4px 12px rgba(45,55,72,.06),0 16px 32px rgba(45,55,72,.1)}
.card-media{position:relative;aspect-ratio:3/2;background:var(--mist);overflow:hidden;cursor:zoom-in}
.card-media img{transition:transform .3s ease;will-change:transform}
.card:hover .card-media img{transform:scale(1.05)}
.cat{position:absolute;top:12px;left:12px;background:rgba(247,249,248,.92);backdrop-filter:blur(6px);padding:5px 10px;border-radius:999px;font-size:11px;font-weight:600;color:var(--charcoal-2);border:1px solid rgba(255,255,255,.6);z-index:2}
.card-body{padding:18px;display:flex;flex-direction:column;gap:10px;flex:1}
.card-title{font-weight:700;font-size:18px;line-height:1.3}
.card-desc{color:var(--charcoal-2);font-size:14px;line-height:1.5;flex:1}
.card-foot{display:flex;align-items:center;justify-content:space-between;margin-top:6px}
.price{font-weight:700;font-size:18px}
.card-actions{display:flex;gap:8px}
.icon-btn{padding:9px 12px;border-radius:10px;border:0;font-size:13px;font-weight:600;cursor:pointer;transition:.2s}
.icon-btn.add{background:var(--mist);color:var(--charcoal)}
.icon-btn.add:hover{background:#dfeae5}
.icon-btn.buy{background:var(--sage-dark);color:white}
.icon-btn.buy:hover{background:#5a7a60;transform:translateY(-1px)}
.about-wrap{background:white;border-radius:24px;padding:40px;box-shadow:var(--shadow);border:1px solid rgba(45,55,72,.06);max-width:900px;margin:0 auto;display:grid;gap:24px}
@media(min-width:800px){.about-wrap{grid-template-columns:1.1fr .9fr;padding:48px}}
.about h3{margin:0 0 8px;font-size:22px}
.about p{margin:0;color:var(--charcoal-2);line-height:1.65}
.feature-list{display:grid;gap:12px;margin-top:8px}
.feature{display:flex;gap:10px;align-items:flex-start}
.feature-dot{width:22px;height:22px;border-radius:50%;background:var(--mist);display:grid;place-items:center;flex-shrink:0;margin-top:2px;color:var(--sage-dark);font-weight:700;font-size:13px}
.testimonial{background:white;border-radius:16px;padding:24px;box-shadow:var(--shadow);border:1px solid rgba(45,55,72,.06);display:flex;flex-direction:column;gap:16px}
.testimonial-quote{font-size:15px;line-height:1.6;color:var(--charcoal-2);font-style:italic;flex:1}
.testimonial-author{display:flex;align-items:center;gap:12px;padding-top:12px;border-top:1px solid rgba(45,55,72,.06)}
.author-avatar{width:40px;height:40px;border-radius:50%;background:var(--mist);display:grid;place-items:center;font-weight:600;color:var(--sage-dark);font-size:14px;flex-shrink:0}
.author-name{font-weight:600;font-size:14px;color:var(--charcoal)}
.author-role{font-size:12px;color:var(--charcoal-2)}
.faq{max-width:800px;margin:0 auto}
details{background:white;border:1px solid rgba(45,55,72,.08);border-radius:14px;padding:18px 20px;margin-bottom:12px;transition:.2s}
details[open]{box-shadow:var(--shadow)}
summary{cursor:pointer;font-weight:600;list-style:none;display:flex;justify-content:space-between;align-items:center}
summary::-webkit-details-marker{display:none}
summary::after{content:'+';color:var(--sage-dark);font-size:20px;line-height:1;transition:.2s}
details[open] summary::after{transform:rotate(45deg)}
details p{color:var(--charcoal-2);margin:12px 0 0;line-height:1.6}
.downloads{background:white;border:1px solid rgba(45,55,72,.08);border-radius:20px;padding:24px;box-shadow:var(--shadow)}
.download-item{display:flex;align-items:center;justify-content:space-between;padding:14px 0;border-bottom:1px solid rgba(45,55,72,.06);gap:12px;flex-wrap:wrap}
.download-item:last-child{border:0}
.dl-meta{display:flex;flex-direction:column;gap:4px}
.dl-title{font-weight:600}
.dl-sub{font-size:12px;color:var(--charcoal-2)}
.dl-actions{display:flex;gap:8px}
.dl-btn{padding:8px 12px;border-radius:10px;background:var(--mist);border:0;font-size:13px;font-weight:600;cursor:pointer}
.dl-btn.primary{background:var(--sage-dark);color:white}
.cart-btn{display:flex;align-items:center;gap:8px;padding:10px 14px;background:var(--mist);border:1px solid rgba(45,55,72,.08);border-radius:12px;cursor:pointer;font-weight:500;font-size:14px;transition:.2s;position:relative}
.cart-btn:hover{background:#dce7e2;transform:translateY(-1px)}
.cart-count{position:absolute;top:-6px;right:-6px;background:var(--sage-dark);color:white;font-size:11px;min-width:20px;height:20px;border-radius:10px;display:grid;place-items:center;padding:0 5px;font-weight:600;border:2px solid var(--off-white)}
#overlay{position:fixed;inset:0;background:rgba(20,25,22,.4);backdrop-filter:blur(2px);opacity:0;pointer-events:none;transition:.3s;z-index:50}
#overlay.active{opacity:1;pointer-events:auto}
.drawer{position:fixed;top:0;right:0;height:100vh;width:380px;max-width:92vw;background:white;box-shadow:-20px 0 40px rgba(45,55,72,.18);transform:translateX(105%);transition:.35s cubic-bezier(.2,.8,.2,1);z-index:60;display:flex;flex-direction:column;border-left:1px solid rgba(45,55,72,.08)}
.drawer.open{transform:translateX(0)}
.drawer-head{padding:20px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid rgba(45,55,72,.08)}
.drawer-body{flex:1;overflow:auto;padding:16px}
.drawer-foot{padding:16px 20px;border-top:1px solid rgba(45,55,72,.08);background:var(--off-white)}
.empty{padding:40px 20px;text-align:center;color:var(--charcoal-2)}
.cart-item{display:grid;grid-template-columns:56px 1fr auto;gap:12px;padding:12px;border:1px solid rgba(45,55,72,.08);border-radius:12px;margin-bottom:10px;background:var(--off-white);align-items:center}
.cart-item img{width:56px;height:42px;object-fit:cover;border-radius:8px}
.ci-title{font-weight:600;font-size:14px;line-height:1.2}
.ci-price{font-size:13px;color:var(--charcoal-2)}
.ci-remove{background:none;border:0;color:var(--charcoal-2);cursor:pointer;font-size:12px;padding:4px}
.ci-remove:hover{color:#c53030}
.total-row{display:flex;justify-content:space-between;align-items:center;margin-bottom:14px;font-weight:700}
.modal{position:fixed;inset:0;display:grid;place-items:center;z-index:70;opacity:0;pointer-events:none;transition:.3s}
.modal.active{opacity:1;pointer-events:auto}
.modal-backdrop{position:absolute;inset:0;background:rgba(20,25,22,.45);backdrop-filter:blur(4px)}
.modal-card{position:relative;background:white;width:min(520px,92vw);border-radius:20px;box-shadow:0 20px 60px rgba(45,55,72,.25);overflow:hidden;border:1px solid rgba(45,55,72,.08);transform:translateY(10px);transition:.3s}
.modal.active .modal-card{transform:translateY(0)}
.modal-head{padding:20px 24px;border-bottom:1px solid rgba(45,55,72,.08);display:flex;justify-content:space-between;align-items:center}
.modal-body{padding:24px}
.form-row{display:grid;gap:14px;margin-bottom:16px}
@media(min-width:480px){.form-row{grid-template-columns:1fr 1fr}}
label{font-size:13px;font-weight:600;color:var(--charcoal-2);display:block;margin-bottom:6px}
input{width:100%;padding:12px 14px;border-radius:12px;border:1px solid rgba(45,55,72,.15);background:var(--off-white);font-size:15px;outline:none;transition:.2s}
input:focus{border-color:var(--sage-dark);background:white;box-shadow:0 0 0 3px rgba(107,143,113,.15)}
.input-error{border-color:var(--error) !important;background:#fff5f5 !important;box-shadow:0 0 0 3px rgba(197,48,48,.15) !important}
.error-msg{color:var(--error);font-size:12px;margin-top:4px;display:none;font-weight:500}
@keyframes shake{0%,100%{transform:translateX(0)}20%,60%{transform:translateX(-4px)}40%,80%{transform:translateX(4px)}}
.shake{animation:shake 0.4s cubic-bezier(.36,.07,.19,.97) both}
.success-icon{width:56px;height:56px;border-radius:50%;background:linear-gradient(135deg,#A7C4B5,#6B8F71);display:grid;place-items:center;margin:0 auto 16px;color:white;font-size:28px}
.hidden{display:none !important}
.close-btn{background:none;border:0;font-size:22px;cursor:pointer;color:var(--charcoal-2);line-height:1}
#preview-modal .modal-card{width:min(900px,96vw);background:transparent;box-shadow:none;border:0}
#preview-modal .modal-body{padding:0;display:grid;place-items:center}
#preview-modal img{max-width:100%;max-height:85vh;border-radius:12px;box-shadow:0 20px 60px rgba(45,55,72,.3)}
#preview-modal .modal-head{position:absolute;top:16px;right:16px;z-index:2}
#preview-modal .close-btn{background:rgba(247,249,248,.95);width:36px;height:36px;border-radius:50%;display:grid;place-items:center;font-size:20px;color:var(--charcoal);box-shadow:0 4px 12px rgba(45,55,72,.15)}
#preview-modal .close-btn:hover{background:white}
.foot{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:16px}
.ci-qty{display:flex;align-items:center;gap:6px;margin-top:4px}
.qty-btn{width:26px;height:26px;border-radius:8px;border:1px solid rgba(45,55,72,.12);background:white;color:var(--charcoal);font-size:14px;font-weight:700;cursor:pointer;display:grid;place-items:center;transition:.15s;line-height:1;padding:0}
.qty-btn:hover{background:var(--mist);border-color:var(--sage-dark)}
.qty-btn:active{transform:scale(.92)}
.qty-btn:focus-visible{outline:2px solid var(--sage-dark);outline-offset:1px}
.qty-val{min-width:24px;text-align:center;font-weight:600;font-size:14px;color:var(--charcoal);user-select:none}
.ci-subtotal{font-size:13px;color:var(--charcoal-2);margin-top:2px;font-weight:500}
</style>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header><div class="container nav"><a href="index.html" class="brand"><div class="brand-mark"></div>Calm Studio</a><button class="cart-btn" id="cart-btn" aria-label="Open cart"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 20l-5.4-1.6A2 2 0 0 1 2 16.6V6.3a2 2 0 0 1 2.2-2L9 5M15 20l5.4-1.6A2 2 0 0 0 22 16.6V6.3a2 2 0 0 0-2.2-2L15 5"/><path d="M9 5v15M15 5v15M9 10h6"/></svg>Cart<span class="cart-count" id="cart-count">0</span></button></div></header>
<main>
<section class="hero"><div class="container"><h1>Digital tools, templates & apps — made simple</h1><p>A calm boutique studio selling handcrafted Notion templates, React webapps, PDFs, spreadsheets, and tiny desktop utilities. Instant download, lifetime updates.</p><div class="hero-cta"><a href="#shop" class="btn btn-primary">Browse downloads</a><a href="#about" class="btn btn-ghost">About studio</a></div></div></section>
<section id="shop"><div class="container"><div class="section-head"><span class="eyebrow">Shop</span><h2>Everything ready to use</h2><p>Pay once, own forever. All files are delivered instantly after purchase.</p></div><div class="filters" id="filters"><button class="filter active" data-filter="All">All</button><button class="filter" data-filter="Templates">Templates</button><button class="filter" data-filter="Webapps">Webapps</button><button class="filter" data-filter="Apps (.exe)">Apps (.exe)</button><button class="filter" data-filter="PDFs">PDFs</button><button class="filter" data-filter="Spreadsheets">Spreadsheets</button></div><div class="grid" id="products-grid"></div><noscript><p style="text-align:center;color:var(--charcoal-2);margin-top:16px">Please enable JavaScript to view products.</p></noscript></div></section>
<section id="downloads-section" class="hidden"><div class="container"><div class="section-head"><span class="eyebrow">Your library</span><h2>My Downloads</h2><p>Your purchases are saved to this browser. Bookmark this page for access.</p></div><div class="downloads" id="downloads-list"></div></div></section>
<section id="about"><div class="container"><div class="section-head"><span class="eyebrow">About</span><h2>Built for calm, focused creators</h2></div><div class="about-wrap"><div><p>Calm Studio is a one-person practice making small, useful digital products. No bloat, no subscriptions, no dark patterns. Just well-designed tools you can actually finish work with.</p><p style="margin-top:12px">Every product includes clear documentation, lifetime updates, and friendly email support.</p></div><div><div class="feature-list"><div class="feature"><div class="feature-dot">✓</div><div><strong>Instant delivery</strong><br><span style="color:var(--charcoal-2);font-size:14px">Download links + license appear immediately</span></div></div><div class="feature"><div class="feature-dot">✓</div><div><strong>Commercial use</strong><br><span style="color:var(--charcoal-2);font-size:14px">Use in personal and client projects</span></div></div><div class="feature"><div class="feature-dot">✓</div><div><strong>Calm updates</strong><br><span style="color:var(--charcoal-2);font-size:14px">Buy once, get all future versions</span></div></div></div></div></div></div></section>
<section id="testimonials"><div class="container"><div class="section-head"><span class="eyebrow">Loved by creators</span><h2>What people say</h2><p>Real feedback from calm, focused users who've simplified their workflow.</p></div><div class="grid"><div class="testimonial"><p class="testimonial-quote">"The Notion OS template transformed how I manage client work. Clean, intuitive, and actually saves me hours every week. Worth every penny."</p><div class="testimonial-author"><div class="author-avatar">AL</div><div><div class="author-name">Alex Lin</div><div class="author-role">Freelance Designer</div></div></div></div><div class="testimonial"><p class="testimonial-quote">"Finally a portfolio template that doesn't feel bloated. The React app is fast, accessible, and the documentation made setup a breeze."</p><div class="testimonial-author"><div class="author-avatar">MJ</div><div><div class="author-name">Maya J.</div><div class="author-role">Developer & Writer</div></div></div></div><div class="testimonial"><p class="testimonial-quote">"The invoice spreadsheet is my new favorite tool. Auto-tax calculations and clean PDF exports just work. Simple, calm, effective."</p><div class="testimonial-author"><div class="author-avatar">RK</div><div><div class="author-name">Riley K.</div><div class="author-role">Small Business Owner</div></div></div></div></div></div></section>
<section id="faq"><div class="container"><div class="section-head"><span class="eyebrow">FAQ</span><h2>Questions, answered</h2></div><div class="faq"><details open><summary>What do I get after purchase?</summary><p>Immediate access to download files, a personal license key, and an email receipt. Your purchases are also saved in "My Downloads" on this device via localStorage.</p></details><details><summary>How do I connect real payments?</summary><p>Replace the "Simulate Payment" button with a real checkout. The fastest options: create a product in Stripe Payment Links, LemonSqueezy, or Gumroad, then paste that checkout URL on the buy buttons. For full control, swap the simulate function in the code with Stripe Checkout (server-side) and deliver files from secure storage after webhook confirmation.</p></details><details><summary>Can I use these for client work?</summary><p>Yes. The personal license covers unlimited personal and commercial client projects. You cannot resell or redistribute the source files themselves.</p></details><details><summary>Do you offer refunds?</summary><p>Because these are digital downloads, I offer fixes and support instead of refunds. If something is truly broken for your setup, email within 14 days and I'll make it right.</p></details></div></div></section>
</main>
<footer><div class="container foot"><div>© <span id="year"></span> Calm Studio — made with quiet focus</div><div style="display:flex;gap:16px"><a href="#shop">Shop</a><a href="#about">About</a><a href="#faq">FAQ</a><a href="privacy.html">Privacy</a><a href="terms.html">Terms</a></div></div></footer>
<div id="overlay"></div>
<aside class="drawer" id="cart-drawer" aria-hidden="true"><div class="drawer-head"><strong>Your Cart</strong><button class="close-btn" id="cart-close" aria-label="Close">×</button></div><div class="drawer-body" id="cart-items"></div><div class="drawer-foot"><div class="total-row"><span>Total</span><span id="cart-total">$0</span></div><button class="btn btn-primary" style="width:100%" id="checkout-btn">Checkout</button></div></aside>
<div class="modal" id="checkout-modal" aria-hidden="true"><div class="modal-backdrop" id="modal-backdrop"></div><div class="modal-card"><div class="modal-head"><strong id="modal-title">Checkout</strong><button class="close-btn" id="modal-close">×</button></div><div class="modal-body"><div id="checkout-form"><div class="form-row"><div><label for="name">Name</label><input id="name" placeholder="Avery Chen" autocomplete="name"><span id="name-error" class="error-msg">Please enter your name</span></div><div><label for="email">Email</label><input id="email" type="email" placeholder="you@domain.com" autocomplete="email"><span id="email-error" class="error-msg">Please enter a valid email</span></div></div><div style="display:flex;gap:12px;justify-content:center;margin:16px 0;color:var(--charcoal-2);font-size:12px;font-weight:500;"><span style="display:flex;align-items:center;gap:4px">🔒 Secure</span><span style="display:flex;align-items:center;gap:4px">⚡ Instant</span><span style="display:flex;align-items:center;gap:4px">♻️ Lifetime updates</span></div><a href="#" id="license-trigger" style="font-size:13px;color:var(--charcoal-2);text-decoration:underline;text-underline-offset:3px;display:block;text-align:center;margin-top:12px">📜 View License Terms</a><p style="font-size:13px;color:var(--charcoal-2);margin:0 0 16px">This is a demo. No card needed — click simulate to generate license & downloads.</p><button class="btn btn-primary" id="pay-btn" style="width:100%">Simulate Payment</button></div><div id="checkout-success" class="hidden" style="text-align:center"><div class="success-icon">✓</div><h3 style="margin:0 0 6px">Payment successful</h3><p style="color:var(--charcoal-2);margin:0 0 16px">Your files are ready. We also saved them to My Downloads.</p><div id="success-list" style="text-align:left;background:var(--off-white);border:1px solid rgba(45,55,72,.08);border-radius:12px;padding:12px;margin-bottom:16px"></div><button class="btn btn-ghost" id="continue-btn" style="width:100%">Continue shopping</button></div></div></div></div>
<div class="modal" id="license-modal" aria-hidden="true"><div class="modal-backdrop" id="license-backdrop"></div><div class="modal-card"><div class="modal-head"><strong id="license-title">License Terms</strong><button class="close-btn" id="license-close" aria-label="Close license">×</button></div><div class="modal-body"><div style="font-size:14px;line-height:1.7;color:var(--charcoal-2)"><p style="margin:0 0 16px"><strong>📦 Calm Studio License</strong></p><p style="margin:0 0 12px"><strong>✅ You may:</strong></p><ul style="margin:0 0 16px 20px;padding:0;list-style:disc"><li>Use this product in personal and commercial client projects</li><li>Modify, adapt, or integrate it into your own workflows</li><li>Receive all future updates for the purchased version, free of charge</li></ul><p style="margin:0 0 12px"><strong>❌ You may not:</strong></p><ul style="margin:0 0 16px 20px;padding:0;list-style:disc"><li>Resell, redistribute, or share the original files or source code</li><li>Offer the product as a standalone template, tool, or service</li><li>Remove copyright notices or claim authorship</li></ul><p style="margin:0 0 12px"><strong>🔄 Updates & Support:</strong></p><ul style="margin:0 0 16px 20px;padding:0;list-style:disc"><li>Lifetime updates are included for the purchased version</li><li>Email support is available for setup, bugs, or compatibility issues</li></ul><p style="margin:0;font-size:13px;color:var(--charcoal-2);font-style:italic">By purchasing, you agree to these terms. Thank you for supporting independent creators.</p></div></div></div></div>
<div class="modal" id="preview-modal" aria-hidden="true"><div class="modal-backdrop" id="preview-backdrop"></div><div class="modal-card"><div class="modal-head"><button class="close-btn" id="preview-close" aria-label="Close preview">×</button></div><div class="modal-body"><img id="preview-image" src="" alt="Product preview"></div></div></div>
<script>
(() => {
const PRODUCTS = [
{id:'notion-os',title:'Notion Business OS Template',price:19,category:'Templates',description:'Complete workspace for clients, projects, tasks and finance tracking.',version:'v2.1',image:"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='400' viewBox='0 0 600 400'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop offset='0%25' stop-color='%23E8F0EE'/%3E%3Cstop offset='100%25' stop-color='%23A7C4B5'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect fill='url(%23g)' width='600' height='400'/%3E%3Ctext x='50%25' y='50%25' dominant-baseline='middle' text-anchor='middle' font-family='sans-serif' font-size='26' fill='%232D3748' font-weight='600'%3ENotion OS%3C/text%3E%3C/svg%3E"},
{id:'portfolio-webapp',title:'Minimal Portfolio Webapp (React)',price:49,category:'Webapps',description:'Fast, accessible portfolio with CMS, blog, and contact form.',version:'v1.4',image:"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='400' viewBox='0 0 600 400'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop offset='0%25' stop-color='%23F7F9F8'/%3E%3Cstop offset='100%25' stop-color='%23E8F0EE'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect fill='url(%23g)' width='600' height='400'/%3E%3Ctext x='50%25' y='50%25' dominant-baseline='middle' text-anchor='middle' font-family='sans-serif' font-size='26' fill='%232D3748' font-weight='600'%3EPortfolio App%3C/text%3E%3C/svg%3E"},
{id:'invoice-sheet',title:'Invoice Generator Spreadsheet',price:12,category:'Spreadsheets',description:'Google Sheets + Excel template with auto-tax, branding, and PDF export.',version:'v3.0',image:"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='400' viewBox='0 0 600 400'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop offset='0%25' stop-color='%23E8F0EE'/%3E%3Cstop offset='100%25' stop-color='%23D6E5DD'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect fill='url(%23g)' width='600' height='400'/%3E%3Ctext x='50%25' y='50%25' dominant-baseline='middle' text-anchor='middle' font-family='sans-serif' font-size='26' fill='%232D3748' font-weight='600'%3EInvoice Sheet%3C/text%3E%3C/svg%3E"},
{id:'resizer-exe',title:'Photo Batch Resizer (.exe)',price:29,category:'Apps (.exe)',description:'Windows utility to resize, compress, and rename thousands of photos offline.',version:'v1.2',image:"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='400' viewBox='0 0 600 400'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop offset='0%25' stop-color='%23DDE9E3'/%3E%3Cstop offset='100%25' stop-color='%23A7C4B5'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect fill='url(%23g)' width='600' height='400'/%3E%3Ctext x='50%25' y='50%25' dominant-baseline='middle' text-anchor='middle' font-family='sans-serif' font-size='26' fill='%232D3748' font-weight='600'%3EResizer.exe%3C/text%3E%3C/svg%3E"},
{id:'saas-ui',title:'SaaS Dashboard UI Kit',price:24,category:'Templates',description:'Figma + HTML components for analytics, settings, and billing flows.',version:'v2.5',image:"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='400' viewBox='0 0 600 400'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop offset='0%25' stop-color='%23C8D9CF'/%3E%3Cstop offset='100%25' stop-color='%23A7C4B5'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect fill='url(%23g)' width='600' height='400'/%3E%3Ctext x='50%25' y='50%25' dominant-baseline='middle' text-anchor='middle' font-family='sans-serif' font-size='26' fill='%232D3748' font-weight='600'%3EDashboard UI%3C/text%3E%3C/svg%3E"},
{id:'planner-pdf',title:'Project Planner PDF Pack',price:15,category:'PDFs',description:'Printable 90-day planner, weekly reviews, and habit trackers.',version:'v1.0',image:"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='400' viewBox='0 0 600 400'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop offset='0%25' stop-color='%23F0F5F3'/%3E%3Cstop offset='100%25' stop-color='%23E8F0EE'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect fill='url(%23g)' width='600' height='400'/%3E%3Ctext x='50%25' y='50%25' dominant-baseline='middle' text-anchor='middle' font-family='sans-serif' font-size='26' fill='%232D3748' font-weight='600'%3EPlanner PDF%3C/text%3E%3C/svg%3E"}
];
const $ = s => document.querySelector(s);
const grid = $('#products-grid'), cartBtn = $('#cart-btn'), cartCount = $('#cart-count'), drawer = $('#cart-drawer'), overlay = $('#overlay'), cartItems = $('#cart-items'), cartTotal = $('#cart-total'), checkoutBtn = $('#checkout-btn'), modal = $('#checkout-modal'), payBtn = $('#pay-btn'), successList = $('#success-list');
let cart = JSON.parse(sessionStorage.getItem('cs_cart') || '[]'), filter = 'All';
function money(n){ return '$' + (Math.round(n * 100) / 100).toFixed(2).replace(/\.00$/, '') }
function saveCart(){ sessionStorage.setItem('cs_cart', JSON.stringify(cart)) }
function renderProducts(){ grid.innerHTML = PRODUCTS.filter(p => filter==='All' || p.category===filter).map(p => `<article class="card"><div class="card-media"><img src="${p.image}" alt="${p.title}" data-preview="${p.image}"><span class="cat">${p.category}</span></div><div class="card-body"><div class="card-title">${p.title} <span style="font-weight:500;color:var(--charcoal-2);font-size:13px;margin-left:6px">${p.version||''}</span></div><div class="card-desc">${p.description}</div><div class="card-foot"><div class="price">${money(p.price)}</div><div class="card-actions"><button class="icon-btn add" data-add="${p.id}">Add to Cart</button><button class="icon-btn buy" data-buy="${p.id}">Buy Now</button></div></div></div></article>`).join(''); }
function updateCartUI(){ const count = cart.reduce((a,c)=>a+c.qty,0); cartCount.textContent = count; cartCount.style.display = count? 'grid':'none'; if(cart.length===0){ cartItems.innerHTML = `<div class="empty">Your cart is empty.<br><span style="font-size:13px">Add something calm.</span></div>`; cartTotal.textContent = '$0'; checkoutBtn.disabled = true; checkoutBtn.style.opacity = .6; return; } checkoutBtn.disabled = false; checkoutBtn.style.opacity = 1; cartItems.innerHTML = cart.map(item => `<div class="cart-item"><img src="${item.image}" alt=""><div style="min-width:0"><div class="ci-title">${item.title}</div><div class="ci-price">${money(item.price)} each</div><div class="ci-qty"><button class="qty-btn" data-dec="${item.id}" aria-label="Decrease quantity" title="Decrease">−</button><span class="qty-val">${item.qty}</span><button class="qty-btn" data-inc="${item.id}" aria-label="Increase quantity" title="Increase">+</button></div><div class="ci-subtotal">Subtotal: ${money(item.price * item.qty)}</div></div><button class="ci-remove" data-remove="${item.id}" title="Remove">✕</button></div>`).join(''); const total = cart.reduce((a,c)=>a + c.price*c.qty,0); cartTotal.textContent = money(total); }
function addToCart(id){ const p = PRODUCTS.find(x=>x.id===id); const existing = cart.find(x=>x.id===id); if(existing) existing.qty++; else cart.push({...p, qty:1}); saveCart(); updateCartUI(); openDrawer(); }
function buyNow(id){ const p = PRODUCTS.find(x=>x.id===id); cart = [{...p, qty:1}]; saveCart(); updateCartUI(); openCheckout(); }
function removeFromCart(id){ cart = cart.filter(x=>x.id!==id); saveCart(); updateCartUI(); }
function increaseQty(id){ const item = cart.find(x=>x.id===id); if(item){ item.qty++; saveCart(); updateCartUI(); } }
function decreaseQty(id){ const item = cart.find(x=>x.id===id); if(item){ item.qty--; if(item.qty<=0){ cart = cart.filter(x=>x.id!==id); } saveCart(); updateCartUI(); } }
function openDrawer(){ drawer.classList.add('open'); overlay.classList.add('active'); drawer.setAttribute('aria-hidden','false') }
function closeDrawer(){ drawer.classList.remove('open'); overlay.classList.remove('active'); drawer.setAttribute('aria-hidden','true') }
function openCheckout(){ closeDrawer(); modal.classList.add('active'); $('#checkout-form').classList.remove('hidden'); $('#checkout-success').classList.add('hidden'); }
function closeModal(){ modal.classList.remove('active') }
function showError(inputId, msg){ const input = $(`#${inputId}`); const error = $(`#${inputId}-error`); if(!input || !error) return; input.classList.add('input-error'); input.classList.add('shake'); error.textContent = msg; error.style.display = 'block'; setTimeout(() => input.classList.remove('shake'), 400); }
function clearError(inputId){ const input = $(`#${inputId}`); const error = $(`#${inputId}-error`); if(!input || !error) return; input.classList.remove('input-error'); error.style.display = 'none'; }
['name', 'email'].forEach(id => $(`#${id}`)?.addEventListener('input', () => clearError(id)));
function handlePayment(){ const name = $('#name').value.trim(); const email = $('#email').value.trim(); let isValid = true; if(!name){ showError('name', 'Name is required'); isValid = false; } if(!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)){ showError('email', 'Please enter a valid email'); isValid = false; } if(!isValid) return; const purchases = JSON.parse(localStorage.getItem('cs_purchases')||'[]'); const now = new Date().toISOString(); const newItems = cart.map(item => ({id: item.id + '-' + Date.now() + '-' + Math.random().toString(36).slice(2,5), productId: item.id, title: item.title, price: item.price, date: now, version: item.version || '', image: item.image})); localStorage.setItem('cs_purchases', JSON.stringify([...newItems, ...purchases])); localStorage.setItem('cs_customer', JSON.stringify({name,email})); successList.innerHTML = newItems.map(it => `<div style="display:flex;justify-content:space-between;align-items:center;padding:8px 0;border-bottom:1px solid rgba(0,0,0,.06);gap:10px;flex-wrap:wrap"><div><div style="font-weight:600">${it.title} <span style="font-weight:500;color:#6b7280;font-size:12px">${it.version}</span></div></div><button class="dl-btn primary" data-demo-dl="${it.title}">Download</button></div>`).join(''); $('#checkout-form').classList.add('hidden'); $('#checkout-success').classList.remove('hidden'); cart = []; saveCart(); updateCartUI(); renderDownloads(); }
function renderDownloads(){ const purchases = JSON.parse(localStorage.getItem('cs_purchases')||'[]'); const section = $('#downloads-section'); const list = $('#downloads-list'); if(purchases.length===0){ section.classList.add('hidden'); return } section.classList.remove('hidden'); list.innerHTML = purchases.map(p => `<div class="download-item"><div class="dl-meta"><span class="dl-title">${p.title} <span style="font-weight:500;color:#6b7280;font-size:12px">${p.version||''}</span></span><span class="dl-sub">Purchased ${new Date(p.date).toLocaleDateString()}</span></div><div class="dl-actions"><button class="dl-btn" data-remove-dl="${p.id}" title="Remove from list">Remove</button><button class="dl-btn primary" data-demo-dl="${p.title}">Download</button></div></div>`).join(''); }
function removeDownload(id){ const purchases = JSON.parse(localStorage.getItem('cs_purchases')||'[]'); localStorage.setItem('cs_purchases', JSON.stringify(purchases.filter(p => p.id !== id))); renderDownloads(); }
const previewModal = $('#preview-modal'), previewImage = $('#preview-image'), previewClose = $('#preview-close'), previewBackdrop = $('#preview-backdrop');
function openPreview(src){ previewImage.src = src; previewModal.classList.add('active'); previewModal.setAttribute('aria-hidden','false'); document.body.style.overflow = 'hidden'; previewClose.focus(); }
function closePreview(){ previewModal.classList.remove('active'); previewModal.setAttribute('aria-hidden','true'); document.body.style.overflow = ''; previewImage.src = ''; }
const licenseModal = $('#license-modal'), licenseTrigger = $('#license-trigger'), licenseClose = $('#license-close'), licenseBackdrop = $('#license-backdrop');
function openLicense(e){ e?.preventDefault(); licenseModal.classList.add('active'); licenseModal.setAttribute('aria-hidden','false'); licenseClose.focus(); }
function closeLicense(){ licenseModal.classList.remove('active'); licenseModal.setAttribute('aria-hidden','true'); }
licenseTrigger?.addEventListener('click', openLicense); licenseClose?.addEventListener('click', closeLicense); licenseBackdrop?.addEventListener('click', closeLicense);
grid?.addEventListener('click', e=>{ const img = e.target.closest('.card-media img'); if(img && img.dataset.preview){ e.preventDefault(); openPreview(img.dataset.preview); } });
previewClose?.addEventListener('click', closePreview); previewBackdrop?.addEventListener('click', closePreview);
document.addEventListener('keydown', e=>{ if(e.key==='Escape'){ closeDrawer(); closeModal(); if(previewModal.classList.contains('active')) closePreview(); if(licenseModal.classList.contains('active')) closeLicense(); } });
document.getElementById('filters').addEventListener('click', e=>{ const btn = e.target.closest('.filter'); if(!btn) return; document.querySelectorAll('.filter').forEach(b=>b.classList.remove('active')); btn.classList.add('active'); filter = btn.dataset.filter; renderProducts(); });
grid.addEventListener('click', e=>{ const add = e.target.closest('[data-add]'); const buy = e.target.closest('[data-buy]'); if(add) addToCart(add.dataset.add); if(buy) buyNow(buy.dataset.buy); });
cartBtn.addEventListener('click', openDrawer); $('#cart-close').addEventListener('click', closeDrawer); overlay.addEventListener('click', ()=>{ closeDrawer(); closeModal(); closeLicense(); closePreview(); });
cartItems.addEventListener('click', e=>{ const r = e.target.closest('[data-remove]'); const inc = e.target.closest('[data-inc]'); const dec = e.target.closest('[data-dec]'); if(r) removeFromCart(r.dataset.remove); if(inc) increaseQty(inc.dataset.inc); if(dec) decreaseQty(dec.dataset.dec); });
checkoutBtn.addEventListener('click', openCheckout); $('#modal-close').addEventListener('click', closeModal); $('#modal-backdrop').addEventListener('click', closeModal);
payBtn.addEventListener('click', handlePayment); $('#continue-btn').addEventListener('click', ()=>{ closeModal(); window.scrollTo({top:0,behavior:'smooth'}) });
successList.addEventListener('click', e=>{ const d = e.target.closest('[data-demo-dl]'); if(d) alert(`Demo download for ${d.dataset.demoDl}`) });
$('#downloads-list').addEventListener('click', e=>{ const r = e.target.closest('[data-remove-dl]'); if(r) removeDownload(r.dataset.removeDl); const d = e.target.closest('[data-demo-dl]'); if(d) alert(`Starting download for ${d.dataset.demoDl}`) });
renderProducts(); updateCartUI(); renderDownloads(); document.getElementById('year').textContent = new Date().getFullYear();
const saved = JSON.parse(localStorage.getItem('cs_customer')||'{}'); if(saved.name) $('#name').value = saved.name; if(saved.email) $('#email').value = saved.email;
})();
</script>
<button id="backToTop" class="back-to-top" aria-label="Back to top"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 15l-6-6-6 6"/></svg></button>
<script>(function(){const b=document.getElementById('backToTop');if(!b)return;const t=400;function u(){window.scrollY>t?b.classList.add('show'):b.classList.remove('show')}window.addEventListener('scroll',u,{passive:true});b.addEventListener('click',()=>window.scrollTo({top:0,behavior:'smooth'}));u()})();</script>
</body>
</html>