@mevdragon/vidfarm-devcli 0.15.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/farmville-saas-ux/SKILL.md +156 -0
- package/.agents/skills/farmville-saas-ux/assets/starter.html +294 -0
- package/.agents/skills/farmville-saas-ux/references/components.md +340 -0
- package/.agents/skills/farmville-saas-ux/references/porting-guide.md +121 -0
- package/.agents/skills/farmville-saas-ux/references/tokens.md +271 -0
- package/.agents/skills/vidfarm-media/SKILL.md +2 -1
- package/.agents/skills/vidfarm-media/references/tts.md +20 -1
- package/demo/dist/app.css +1 -1
- package/demo/dist/app.js +74 -74
- package/dist/src/account-pages-legacy.js +2 -2
- package/dist/src/app.js +682 -12
- package/dist/src/config.js +13 -0
- package/dist/src/editor-chat.js +3 -2
- package/dist/src/frontend/homepage-client.js +211 -2
- package/dist/src/frontend/homepage-shared.js +197 -0
- package/dist/src/frontend/homepage-store.js +39 -1
- package/dist/src/frontend/homepage-view.js +150 -5
- package/dist/src/homepage.js +234 -18
- package/dist/src/landing-page.js +367 -0
- package/dist/src/primitive-registry.js +278 -2
- package/dist/src/reskin/agency-page.js +255 -0
- package/dist/src/reskin/calendar-page.js +252 -0
- package/dist/src/reskin/chat-page.js +414 -0
- package/dist/src/reskin/discover-page.js +380 -0
- package/dist/src/reskin/document.js +74 -0
- package/dist/src/reskin/help-page.js +318 -0
- package/dist/src/reskin/index-page.js +62 -0
- package/dist/src/reskin/job-runs-page.js +249 -0
- package/dist/src/reskin/library-page.js +515 -0
- package/dist/src/reskin/login-page.js +225 -0
- package/dist/src/reskin/pricing-page.js +359 -0
- package/dist/src/reskin/settings-page.js +353 -0
- package/dist/src/reskin/theme.js +265 -0
- package/dist/src/services/serverless-records.js +63 -0
- package/dist/src/services/swipe-customize.js +434 -0
- package/package.json +1 -1
- package/public/assets/homepage-client-app.js +23 -23
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
// /reskin/login — the auth screen ported into the farmville design system.
|
|
2
|
+
//
|
|
3
|
+
// Bare chrome (no shared top nav / footer): an auth screen owns its whole
|
|
4
|
+
// canvas, so we render just the body over a warm sunny background. A two-column
|
|
5
|
+
// composition — a sunlit brand/marketing panel on the left, a floating white
|
|
6
|
+
// auth card on the right — collapses to a single centered card on small screens.
|
|
7
|
+
//
|
|
8
|
+
// Faithfully mirrors src/account-pages-legacy.ts → renderLoginPage. The legacy
|
|
9
|
+
// page is OTP-first with a password alternative; the design brief here favors a
|
|
10
|
+
// classic email + password form with a (visual) Log in / Sign up pill toggle, so
|
|
11
|
+
// the primary form posts to the REAL password endpoint /login/password (mode=
|
|
12
|
+
// password) and the ghost secondary button links to the REAL passwordless OTP
|
|
13
|
+
// flow at /login?mode=otp — both endpoints are honest.
|
|
14
|
+
import { reskinDocument } from "./document.js";
|
|
15
|
+
// Real login endpoints from the live app (src/app.ts).
|
|
16
|
+
const PASSWORD_ACTION = "/login/password?mode=password";
|
|
17
|
+
const OTP_HREF = "/login?mode=otp";
|
|
18
|
+
const EYE = `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg>`;
|
|
19
|
+
const MAIL = `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="5" width="18" height="14" rx="3"/><path d="m3.5 7 8.5 6 8.5-6"/></svg>`;
|
|
20
|
+
export function renderReskinLogin() {
|
|
21
|
+
const body = `
|
|
22
|
+
<main class="rk-login">
|
|
23
|
+
<div class="rk-login-art">
|
|
24
|
+
<div class="rk-login-art-sky"></div>
|
|
25
|
+
<span class="rk-login-blob rk-login-blob-a"></span>
|
|
26
|
+
<span class="rk-login-blob rk-login-blob-b"></span>
|
|
27
|
+
<div class="rk-login-art-inner">
|
|
28
|
+
<a class="rk-brand rk-login-brand" href="/">
|
|
29
|
+
<span class="rk-brand-mark">V</span>vidfarm
|
|
30
|
+
</a>
|
|
31
|
+
<div class="rk-login-art-copy">
|
|
32
|
+
<span class="rk-badge rk-login-eyebrow">Welcome back to the farm</span>
|
|
33
|
+
<h1 class="rk-login-hed">A week of content, made in an afternoon.</h1>
|
|
34
|
+
<p class="rk-login-lede">Sign in to spin up short-form ads from your own clips — punchy hooks, UGC energy, captions that pop.</p>
|
|
35
|
+
<ul class="rk-login-feats">
|
|
36
|
+
<li><span class="rk-login-feat-mark" aria-hidden="true"></span> Mine & tag clips automatically</li>
|
|
37
|
+
<li><span class="rk-login-feat-mark" aria-hidden="true"></span> Swipe templates into finished ads</li>
|
|
38
|
+
<li><span class="rk-login-feat-mark" aria-hidden="true"></span> Publish straight to your channels</li>
|
|
39
|
+
</ul>
|
|
40
|
+
</div>
|
|
41
|
+
<figure class="rk-login-quote rk-glass">
|
|
42
|
+
<div class="rk-login-quote-avatar">DV</div>
|
|
43
|
+
<blockquote>
|
|
44
|
+
<p>"We ship a full week of ads before lunch now. It feels like cheating."</p>
|
|
45
|
+
<figcaption>Dylan Vane · Founder, Studio Co</figcaption>
|
|
46
|
+
</blockquote>
|
|
47
|
+
</figure>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<div class="rk-login-pane">
|
|
52
|
+
<div class="rk-login-card">
|
|
53
|
+
<a class="rk-brand rk-login-card-brand" href="/">
|
|
54
|
+
<span class="rk-brand-mark">V</span>vidfarm
|
|
55
|
+
</a>
|
|
56
|
+
|
|
57
|
+
<div class="rk-login-head">
|
|
58
|
+
<h2 class="rk-login-title" data-rk-title>Welcome back</h2>
|
|
59
|
+
<p class="rk-muted" data-rk-subtitle>Log in to pick up where you left off.</p>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<div class="rk-login-seg" role="tablist" aria-label="Log in or sign up">
|
|
63
|
+
<span class="rk-login-seg-thumb" data-rk-thumb></span>
|
|
64
|
+
<button type="button" class="rk-login-seg-btn is-active" data-rk-seg="login" aria-selected="true">Log in</button>
|
|
65
|
+
<button type="button" class="rk-login-seg-btn" data-rk-seg="signup" aria-selected="false">Sign up</button>
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
<form class="rk-stack rk-login-form" method="post" action="${PASSWORD_ACTION}">
|
|
69
|
+
<div class="rk-field">
|
|
70
|
+
<label class="rk-label" for="rk-login-email">Email</label>
|
|
71
|
+
<input class="rk-input" id="rk-login-email" type="email" name="email" placeholder="you@studio.co" autocomplete="email" required />
|
|
72
|
+
</div>
|
|
73
|
+
<div class="rk-field">
|
|
74
|
+
<div class="rk-login-label-row">
|
|
75
|
+
<label class="rk-label" for="rk-login-pass">Password</label>
|
|
76
|
+
<a class="rk-login-forgot" href="${OTP_HREF}" data-rk-forgot>Forgot password?</a>
|
|
77
|
+
</div>
|
|
78
|
+
<div class="rk-input-group">
|
|
79
|
+
<input class="rk-input" id="rk-login-pass" type="password" name="password" placeholder="••••••••" autocomplete="current-password" required />
|
|
80
|
+
<button class="rk-btn rk-btn-ghost rk-btn-sm rk-login-eye" type="button" data-rk-reveal="rk-login-pass" aria-label="Show password">${EYE}</button>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
<button class="rk-btn rk-btn-gold rk-btn-lg rk-btn-block rk-login-submit" type="submit" data-rk-submit>Log in <span class="rk-arrow">→</span></button>
|
|
84
|
+
</form>
|
|
85
|
+
|
|
86
|
+
<div class="rk-login-divider"><span>or</span></div>
|
|
87
|
+
|
|
88
|
+
<a class="rk-btn rk-btn-ghost rk-btn-lg rk-btn-block rk-login-alt" href="${OTP_HREF}">${MAIL} Email me a login code</a>
|
|
89
|
+
|
|
90
|
+
<p class="rk-login-foot" data-rk-foot>
|
|
91
|
+
New to vidfarm? <a href="#" data-rk-foot-link>Start a free trial</a>
|
|
92
|
+
</p>
|
|
93
|
+
</div>
|
|
94
|
+
<p class="rk-login-legal">By continuing you agree to our <a href="#">Terms</a> & <a href="#">Privacy Policy</a>.</p>
|
|
95
|
+
</div>
|
|
96
|
+
</main>`;
|
|
97
|
+
const pageCss = `
|
|
98
|
+
.rk-login{min-height:100vh;display:grid;grid-template-columns:1.05fr .95fr;
|
|
99
|
+
background:radial-gradient(120% 90% at 100% 0%,var(--rk-gold-tint) 0%,transparent 55%),var(--rk-bg)}
|
|
100
|
+
@media(max-width:920px){.rk-login{grid-template-columns:1fr}}
|
|
101
|
+
|
|
102
|
+
/* ── left: sunlit brand / marketing panel ── */
|
|
103
|
+
.rk-login-art{position:relative;overflow:hidden;display:flex;padding:56px clamp(2rem,4vw,4rem)}
|
|
104
|
+
@media(max-width:920px){.rk-login-art{display:none}}
|
|
105
|
+
.rk-login-art-sky{position:absolute;inset:0;z-index:0;background:
|
|
106
|
+
radial-gradient(72% 55% at 22% 12%,rgba(255,244,214,.96),transparent 62%),
|
|
107
|
+
radial-gradient(60% 55% at 92% 96%,rgba(255,199,56,.42),transparent 60%),
|
|
108
|
+
linear-gradient(158deg,#89ccf3 0%,#b7e0fa 42%,#ffe7c9 100%)}
|
|
109
|
+
.rk-login-blob{position:absolute;z-index:0;border-radius:var(--rk-r-full);filter:blur(2px);
|
|
110
|
+
background:rgba(255,255,255,.55)}
|
|
111
|
+
.rk-login-blob-a{width:220px;height:120px;top:16%;right:12%;box-shadow:60px 20px 0 -18px rgba(255,255,255,.5)}
|
|
112
|
+
.rk-login-blob-b{width:150px;height:84px;bottom:24%;left:-30px;background:rgba(255,255,255,.4)}
|
|
113
|
+
.rk-login-art-inner{position:relative;z-index:1;display:flex;flex-direction:column;gap:32px;
|
|
114
|
+
justify-content:space-between;width:100%;max-width:440px;margin:auto}
|
|
115
|
+
.rk-login-brand{font-size:22px;color:var(--rk-ink)}
|
|
116
|
+
.rk-login-brand .rk-brand-mark{width:30px;height:30px;font-size:17px}
|
|
117
|
+
.rk-login-art-copy{display:grid;gap:18px}
|
|
118
|
+
.rk-login-eyebrow{justify-self:start;background:rgba(255,255,255,.72);border-color:rgba(255,255,255,.9);
|
|
119
|
+
backdrop-filter:blur(6px);color:var(--rk-n-700)}
|
|
120
|
+
.rk-login-hed{font-size:clamp(2rem,3.4vw,2.9rem);line-height:1.05;letter-spacing:-.035em;color:var(--rk-ink);
|
|
121
|
+
max-width:12ch;text-wrap:balance}
|
|
122
|
+
.rk-login-lede{font-size:var(--rk-text-lg);line-height:1.5;color:var(--rk-n-700);max-width:34ch}
|
|
123
|
+
.rk-login-feats{list-style:none;margin:0;padding:0;display:grid;gap:12px}
|
|
124
|
+
.rk-login-feats li{display:flex;align-items:center;gap:11px;font-size:15px;font-weight:600;color:var(--rk-n-800)}
|
|
125
|
+
.rk-login-feat-mark{width:7px;height:7px;border-radius:var(--rk-r-full);background:var(--rk-gold-500);
|
|
126
|
+
box-shadow:0 0 0 4px var(--rk-gold-tint2);flex:none;margin:0 3px}
|
|
127
|
+
.rk-login-quote{border-radius:var(--rk-r-3xl);padding:18px 20px;display:flex;gap:14px;align-items:flex-start;
|
|
128
|
+
box-shadow:var(--rk-shadow-lg)}
|
|
129
|
+
.rk-login-quote-avatar{width:42px;height:42px;border-radius:var(--rk-r-full);flex:none;display:grid;place-items:center;
|
|
130
|
+
font-family:var(--rk-font-display);font-weight:800;font-size:15px;color:var(--rk-ink);
|
|
131
|
+
background:var(--rk-gold-500);box-shadow:var(--rk-shadow-xs)}
|
|
132
|
+
.rk-login-quote blockquote{margin:0;display:grid;gap:6px}
|
|
133
|
+
.rk-login-quote p{font-size:14px;font-weight:600;color:var(--rk-ink);line-height:1.45}
|
|
134
|
+
.rk-login-quote figcaption{font-size:12px;font-weight:600;color:var(--rk-n-600)}
|
|
135
|
+
|
|
136
|
+
/* ── right: floating auth card ── */
|
|
137
|
+
.rk-login-pane{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16px;
|
|
138
|
+
padding:48px clamp(1.25rem,4vw,3rem)}
|
|
139
|
+
.rk-login-card{width:100%;max-width:412px;background:var(--rk-surface);border:1px solid var(--rk-border);
|
|
140
|
+
border-radius:var(--rk-r-3xl);padding:clamp(28px,3vw,40px);box-shadow:var(--rk-shadow-xl);display:grid;gap:22px}
|
|
141
|
+
.rk-login-card-brand{display:none;font-size:20px}
|
|
142
|
+
@media(max-width:920px){.rk-login-card-brand{display:inline-flex;justify-self:center}}
|
|
143
|
+
.rk-login-head{display:grid;gap:6px;text-align:center}
|
|
144
|
+
.rk-login-title{font-size:var(--rk-text-3xl);letter-spacing:-.03em}
|
|
145
|
+
|
|
146
|
+
/* segmented pill toggle (visual) — gold is reserved for submit, so the active
|
|
147
|
+
thumb is a plain white pill with an ink label */
|
|
148
|
+
.rk-login-seg{position:relative;display:grid;grid-template-columns:1fr 1fr;gap:2px;padding:4px;
|
|
149
|
+
background:var(--rk-n-100);border:1px solid var(--rk-border);border-radius:var(--rk-r-full)}
|
|
150
|
+
.rk-login-seg-thumb{position:absolute;z-index:0;top:4px;left:4px;width:calc(50% - 4px);height:calc(100% - 8px);
|
|
151
|
+
background:#fff;border-radius:var(--rk-r-full);box-shadow:var(--rk-shadow-sm);
|
|
152
|
+
transition:transform var(--rk-dur) var(--rk-ease)}
|
|
153
|
+
.rk-login-seg-thumb.is-right{transform:translateX(100%)}
|
|
154
|
+
.rk-login-seg-btn{position:relative;z-index:1;appearance:none;border:0;background:transparent;cursor:pointer;
|
|
155
|
+
padding:9px 12px;border-radius:var(--rk-r-full);font-family:var(--rk-font-body);font-size:14px;font-weight:600;
|
|
156
|
+
color:var(--rk-n-500);transition:color var(--rk-dur) var(--rk-ease)}
|
|
157
|
+
.rk-login-seg-btn.is-active{color:var(--rk-ink)}
|
|
158
|
+
|
|
159
|
+
.rk-login-form{gap:16px}
|
|
160
|
+
.rk-login-label-row{display:flex;align-items:baseline;justify-content:space-between;gap:8px}
|
|
161
|
+
.rk-login-forgot{font-size:12px;font-weight:600;color:var(--rk-gold-700)}
|
|
162
|
+
.rk-login-forgot:hover{text-decoration:underline}
|
|
163
|
+
.rk-login-eye{padding:0 12px;color:var(--rk-n-500)}
|
|
164
|
+
.rk-login-submit{margin-top:4px}
|
|
165
|
+
|
|
166
|
+
.rk-login-divider{display:flex;align-items:center;gap:14px;color:var(--rk-text-faint);
|
|
167
|
+
font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.08em}
|
|
168
|
+
.rk-login-divider::before,.rk-login-divider::after{content:"";height:1px;flex:1;background:var(--rk-border)}
|
|
169
|
+
.rk-login-alt{color:var(--rk-ink)}
|
|
170
|
+
.rk-login-foot{text-align:center;font-size:14px;color:var(--rk-text-muted)}
|
|
171
|
+
.rk-login-foot a{font-weight:700;color:var(--rk-ink)}
|
|
172
|
+
.rk-login-foot a:hover{color:var(--rk-gold-700)}
|
|
173
|
+
.rk-login-legal{font-size:12px;color:var(--rk-text-faint);text-align:center;max-width:412px}
|
|
174
|
+
.rk-login-legal a{color:var(--rk-text-muted);text-decoration:underline}
|
|
175
|
+
`;
|
|
176
|
+
const script = `
|
|
177
|
+
(function(){
|
|
178
|
+
var root=document;
|
|
179
|
+
// segmented Log in / Sign up toggle — visual only; both keep the real password
|
|
180
|
+
// form, we just relabel copy so the two states read honestly.
|
|
181
|
+
var thumb=root.querySelector('[data-rk-thumb]');
|
|
182
|
+
var title=root.querySelector('[data-rk-title]');
|
|
183
|
+
var subtitle=root.querySelector('[data-rk-subtitle]');
|
|
184
|
+
var submit=root.querySelector('[data-rk-submit]');
|
|
185
|
+
var foot=root.querySelector('[data-rk-foot]');
|
|
186
|
+
var forgot=root.querySelector('[data-rk-forgot]');
|
|
187
|
+
var arrow='<span class="rk-arrow">\\u2192</span>';
|
|
188
|
+
var copy={
|
|
189
|
+
login:{title:'Welcome back',sub:'Log in to pick up where you left off.',btn:'Log in '+arrow,foot:'New to vidfarm? <a href="#" data-rk-foot-link>Start a free trial</a>',forgot:true},
|
|
190
|
+
signup:{title:'Create your studio',sub:'Start making short-form ads in minutes.',btn:'Create account '+arrow,foot:'Already have an account? <a href="#" data-rk-foot-link>Log in</a>',forgot:false}
|
|
191
|
+
};
|
|
192
|
+
root.querySelectorAll('[data-rk-seg]').forEach(function(btn){
|
|
193
|
+
btn.addEventListener('click',function(){
|
|
194
|
+
var mode=btn.getAttribute('data-rk-seg');
|
|
195
|
+
root.querySelectorAll('[data-rk-seg]').forEach(function(b){
|
|
196
|
+
var on=b===btn; b.classList.toggle('is-active',on); b.setAttribute('aria-selected',on?'true':'false');
|
|
197
|
+
});
|
|
198
|
+
if(thumb)thumb.classList.toggle('is-right',mode==='signup');
|
|
199
|
+
var c=copy[mode];
|
|
200
|
+
if(title)title.textContent=c.title;
|
|
201
|
+
if(subtitle)subtitle.textContent=c.sub;
|
|
202
|
+
if(submit)submit.innerHTML=c.btn;
|
|
203
|
+
if(foot)foot.innerHTML=c.foot;
|
|
204
|
+
if(forgot)forgot.style.visibility=c.forgot?'visible':'hidden';
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
// password reveal eye
|
|
208
|
+
root.querySelectorAll('[data-rk-reveal]').forEach(function(btn){
|
|
209
|
+
btn.addEventListener('click',function(){
|
|
210
|
+
var el=root.getElementById(btn.getAttribute('data-rk-reveal'));
|
|
211
|
+
if(!el)return; el.type=el.type==='password'?'text':'password';
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
})();`;
|
|
215
|
+
return reskinDocument({
|
|
216
|
+
title: "vidfarm reskin — Login",
|
|
217
|
+
description: "Reskinned vidfarm login / sign up screen.",
|
|
218
|
+
activeSlug: "login",
|
|
219
|
+
chrome: "bare",
|
|
220
|
+
pageCss,
|
|
221
|
+
body,
|
|
222
|
+
script
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=login-page.js.map
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
// /reskin/pricing — plans + wallet credit top-up, reskinned into the farmville
|
|
2
|
+
// warm-sunny design system using ONLY shared rk-* primitives + a page-scoped
|
|
3
|
+
// rk-pricing-* CSS block + a small self-contained module script.
|
|
4
|
+
//
|
|
5
|
+
// Faithfully mirrors the live vidfarm pricing surface (src/account-pages-legacy.ts):
|
|
6
|
+
// • Paid-plan tiers — Standard $99/mo ("Best value") and Agency $1200/mo, with
|
|
7
|
+
// a Free/local tier added to make the ladder read as a real pricing page.
|
|
8
|
+
// • The credit wallet model — top-ups at $0.03 / credit ($0.02 margin,
|
|
9
|
+
// $0.01 ecosystem liability), "you're only charged for compute — BYO AI
|
|
10
|
+
// keys are never billed."
|
|
11
|
+
// Renders with representative SAMPLE data so it can be viewed without auth. The
|
|
12
|
+
// gold "joy" accent is reserved for the hero plan, the popular credit pack, and
|
|
13
|
+
// the primary CTAs; every other action uses the charcoal/ghost workhorses.
|
|
14
|
+
import { reskinDocument, rkEscape } from "./document.js";
|
|
15
|
+
const PLANS = [
|
|
16
|
+
{
|
|
17
|
+
id: "free",
|
|
18
|
+
kicker: "Get started",
|
|
19
|
+
name: "Starter",
|
|
20
|
+
monthlyUsd: 0,
|
|
21
|
+
yearlyUsd: 0,
|
|
22
|
+
priceSuffix: "forever",
|
|
23
|
+
pitch: "Fork templates, recut with your own footage, and render locally on a vidfarm serve box — no card required.",
|
|
24
|
+
features: [
|
|
25
|
+
"1 publishing channel",
|
|
26
|
+
"Local in-process renders (free)",
|
|
27
|
+
"Community template feed",
|
|
28
|
+
"Bring your own AI keys",
|
|
29
|
+
"Clip library & My Files"
|
|
30
|
+
],
|
|
31
|
+
cta: "Start free",
|
|
32
|
+
ctaStyle: "ghost"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: "standard",
|
|
36
|
+
kicker: "Best value",
|
|
37
|
+
name: "Standard",
|
|
38
|
+
monthlyUsd: 99,
|
|
39
|
+
yearlyUsd: 79,
|
|
40
|
+
priceSuffix: "/mo",
|
|
41
|
+
pitch: "For operators publishing consistently — more channels, unlimited cloud video output, and Swipe-mode auto-recut.",
|
|
42
|
+
features: [
|
|
43
|
+
"10 publishing channels",
|
|
44
|
+
"Unlimited cloud renders",
|
|
45
|
+
"Swipe mode & AI recaption",
|
|
46
|
+
"Bring your own AI keys",
|
|
47
|
+
"Wallet top-ups at $0.03 / credit",
|
|
48
|
+
"Email support"
|
|
49
|
+
],
|
|
50
|
+
cta: "Go Standard",
|
|
51
|
+
ctaStyle: "gold",
|
|
52
|
+
featured: true
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: "agency",
|
|
56
|
+
kicker: "For teams",
|
|
57
|
+
name: "Agency",
|
|
58
|
+
monthlyUsd: 1200,
|
|
59
|
+
yearlyUsd: 960,
|
|
60
|
+
priceSuffix: "/mo",
|
|
61
|
+
pitch: "For studios running many clients — unlimited capacity, per-client key setups, and hands-on support.",
|
|
62
|
+
features: [
|
|
63
|
+
"Unlimited channels",
|
|
64
|
+
"Unlimited videos",
|
|
65
|
+
"Per-client API-key workspaces",
|
|
66
|
+
"Priority Lambda render lane",
|
|
67
|
+
"White-label client library",
|
|
68
|
+
"Live call support"
|
|
69
|
+
],
|
|
70
|
+
cta: "Talk to sales",
|
|
71
|
+
ctaStyle: "ink"
|
|
72
|
+
}
|
|
73
|
+
];
|
|
74
|
+
const PACKS = [
|
|
75
|
+
{ label: "Starter", usd: 20, credits: 666, bonus: 0, note: "~20 cloud renders" },
|
|
76
|
+
{ label: "Studio", usd: 50, credits: 1666, bonus: 84, note: "+5% bonus credits", popular: true },
|
|
77
|
+
{ label: "Scale", usd: 100, credits: 3333, bonus: 334, note: "+10% bonus credits" },
|
|
78
|
+
{ label: "Agency", usd: 250, credits: 8333, bonus: 1167, note: "+14% bonus credits" }
|
|
79
|
+
];
|
|
80
|
+
const FAQS = [
|
|
81
|
+
{
|
|
82
|
+
q: "What exactly is a credit?",
|
|
83
|
+
a: "A credit is $0.03 of compute. Renders, clip scans, and decompose passes draw from your wallet. Bring-your-own AI keys are never billed by vidfarm."
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
q: "Do credits expire?",
|
|
87
|
+
a: "No. Wallet credits roll over forever and the balance auto-scales to zero — you only ever pay for compute you actually run."
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
q: "Can I set spend limits?",
|
|
91
|
+
a: "Yes. Cap usage with per-hour and per-day credit rate limits so long-lived render jobs never surprise you."
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
q: "Local renders are really free?",
|
|
95
|
+
a: "Yep. A vidfarm serve box renders in-process on your machine with no charge — perfect for reusing already-decomposed templates."
|
|
96
|
+
}
|
|
97
|
+
];
|
|
98
|
+
const CHECK = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 12.5l5 5L20 6"/></svg>`;
|
|
99
|
+
function usd(n) {
|
|
100
|
+
return `$${n.toLocaleString("en-US")}`;
|
|
101
|
+
}
|
|
102
|
+
function credits(n) {
|
|
103
|
+
return n.toLocaleString("en-US");
|
|
104
|
+
}
|
|
105
|
+
function planCard(p) {
|
|
106
|
+
const featured = p.featured ? " rk-pricing-plan-featured" : "";
|
|
107
|
+
const badge = p.featured
|
|
108
|
+
? `<span class="rk-pricing-most">Most popular</span>`
|
|
109
|
+
: "";
|
|
110
|
+
const checkTint = p.featured ? "rk-tile-gold" : "rk-tile-green";
|
|
111
|
+
const features = p.features.map((f) => `
|
|
112
|
+
<li class="rk-pricing-feat">
|
|
113
|
+
<span class="rk-tile rk-tile-sm ${checkTint} rk-pricing-check">${CHECK}</span>
|
|
114
|
+
<span>${rkEscape(f)}</span>
|
|
115
|
+
</li>`).join("");
|
|
116
|
+
const priceBlock = p.monthlyUsd === 0
|
|
117
|
+
? `<div class="rk-pricing-price"><span class="rk-pricing-amount" data-rk-price-free>Free</span></div>
|
|
118
|
+
<p class="rk-pricing-price-sub">${rkEscape(p.priceSuffix)}</p>`
|
|
119
|
+
: `<div class="rk-pricing-price">
|
|
120
|
+
<span class="rk-pricing-cur">$</span>
|
|
121
|
+
<span class="rk-pricing-amount" data-rk-price data-rk-monthly="${p.monthlyUsd}" data-rk-yearly="${p.yearlyUsd}">${p.monthlyUsd}</span>
|
|
122
|
+
<span class="rk-pricing-suffix">${rkEscape(p.priceSuffix)}</span>
|
|
123
|
+
</div>
|
|
124
|
+
<p class="rk-pricing-price-sub" data-rk-price-note><span class="rk-strike">${usd(p.monthlyUsd)}</span> billed yearly · save 20%</p>`;
|
|
125
|
+
return `
|
|
126
|
+
<article class="rk-card rk-card-hover rk-pricing-plan${featured}">
|
|
127
|
+
${badge}
|
|
128
|
+
<div class="rk-pricing-plan-head">
|
|
129
|
+
<span class="rk-tile ${p.featured ? "rk-tile-gold" : "rk-tile-ink"} rk-pricing-mono" aria-hidden="true">${rkEscape(p.name.charAt(0))}</span>
|
|
130
|
+
<div>
|
|
131
|
+
<span class="rk-eyebrow ${p.featured ? "" : "rk-pricing-kicker-muted"}">${rkEscape(p.kicker)}</span>
|
|
132
|
+
<h3>${rkEscape(p.name)}</h3>
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
${priceBlock}
|
|
136
|
+
<p class="rk-pricing-pitch">${rkEscape(p.pitch)}</p>
|
|
137
|
+
<a class="rk-btn rk-btn-${p.ctaStyle} rk-btn-block rk-btn-lg" href="#">${rkEscape(p.cta)}<span class="rk-arrow">→</span></a>
|
|
138
|
+
<ul class="rk-pricing-feats">${features}</ul>
|
|
139
|
+
</article>`;
|
|
140
|
+
}
|
|
141
|
+
function packCard(p) {
|
|
142
|
+
const total = p.credits + p.bonus;
|
|
143
|
+
const popular = p.popular ? " rk-pricing-pack-popular" : "";
|
|
144
|
+
const flag = p.popular ? `<span class="rk-pill rk-pill-gold rk-pricing-pack-flag">Most popular</span>` : "";
|
|
145
|
+
const bonusPill = p.bonus > 0
|
|
146
|
+
? `<span class="rk-pill rk-pill-green rk-pricing-pack-bonus">+${credits(p.bonus)} bonus</span>`
|
|
147
|
+
: `<span class="rk-pill rk-pricing-pack-bonus">base rate</span>`;
|
|
148
|
+
return `
|
|
149
|
+
<article class="rk-pricing-pack${popular}">
|
|
150
|
+
${flag}
|
|
151
|
+
<div class="rk-pricing-pack-top">
|
|
152
|
+
<span class="rk-tile rk-tile-sm ${p.popular ? "rk-tile-gold" : "rk-tile-coral"} rk-pricing-mono" aria-hidden="true">${rkEscape(p.label.charAt(0))}</span>
|
|
153
|
+
<span class="rk-pricing-pack-label">${rkEscape(p.label)}</span>
|
|
154
|
+
</div>
|
|
155
|
+
<div class="rk-pricing-pack-credits">${credits(total)}<span>credits</span></div>
|
|
156
|
+
${bonusPill}
|
|
157
|
+
<div class="rk-pricing-pack-price">${usd(p.usd)}<span>one-time</span></div>
|
|
158
|
+
<p class="rk-pricing-pack-note">${rkEscape(p.note)}</p>
|
|
159
|
+
<button type="button" class="rk-btn ${p.popular ? "rk-btn-gold" : "rk-btn-ghost"} rk-btn-block rk-btn-sm">Top up ${usd(p.usd)}</button>
|
|
160
|
+
</article>`;
|
|
161
|
+
}
|
|
162
|
+
export function renderReskinPricing() {
|
|
163
|
+
const planCards = PLANS.map(planCard).join("");
|
|
164
|
+
const packCards = PACKS.map(packCard).join("");
|
|
165
|
+
const faqCards = FAQS.map((f) => `
|
|
166
|
+
<div class="rk-card rk-card-pad-sm rk-pricing-faq">
|
|
167
|
+
<h3>${rkEscape(f.q)}</h3>
|
|
168
|
+
<p class="rk-muted">${rkEscape(f.a)}</p>
|
|
169
|
+
</div>`).join("");
|
|
170
|
+
const trustPills = [
|
|
171
|
+
"Cancel anytime",
|
|
172
|
+
"Transparent per-render billing",
|
|
173
|
+
"BYO AI keys — never billed",
|
|
174
|
+
"Auto-scales to zero"
|
|
175
|
+
].map((t) => `<span class="rk-pill rk-pricing-trust">${t}</span>`).join("");
|
|
176
|
+
const body = `
|
|
177
|
+
<main class="rk-container rk-page rk-pricing">
|
|
178
|
+
|
|
179
|
+
<!-- ── intro ── -->
|
|
180
|
+
<section class="rk-pricing-intro">
|
|
181
|
+
<span class="rk-badge">Simple, sunny pricing</span>
|
|
182
|
+
<h1 class="rk-pricing-title">Ship a week of content<br><span class="rk-pricing-title-accent">in an afternoon.</span></h1>
|
|
183
|
+
<p class="rk-pricing-lede">Start free and render locally. Upgrade when you're publishing daily. Top up a credit wallet for cloud compute — only ever pay for what you render.</p>
|
|
184
|
+
<div class="rk-pricing-toggle" role="group" aria-label="Billing period">
|
|
185
|
+
<button type="button" class="rk-pricing-toggle-btn is-active" data-rk-period="monthly">Monthly</button>
|
|
186
|
+
<button type="button" class="rk-pricing-toggle-btn" data-rk-period="yearly">Yearly <span class="rk-pill rk-pill-gold rk-pricing-save">Save 20%</span></button>
|
|
187
|
+
</div>
|
|
188
|
+
</section>
|
|
189
|
+
|
|
190
|
+
<!-- ── plan cards ── -->
|
|
191
|
+
<section class="rk-pricing-plans">${planCards}</section>
|
|
192
|
+
|
|
193
|
+
<!-- ── credit top-up strip ── -->
|
|
194
|
+
<section class="rk-card rk-pricing-credits">
|
|
195
|
+
<div class="rk-pricing-credits-head">
|
|
196
|
+
<span class="rk-eyebrow">Credit wallet</span>
|
|
197
|
+
<h2>Top up credits, pay only for compute</h2>
|
|
198
|
+
<p class="rk-muted">Every credit is <strong>$0.03</strong> of render compute. Cloud renders, clip scans and decompose passes draw from your wallet — bring-your-own AI keys are never billed. Balance rolls over forever and auto-scales to zero.</p>
|
|
199
|
+
</div>
|
|
200
|
+
<div class="rk-pricing-packs">${packCards}</div>
|
|
201
|
+
<div class="rk-pricing-credits-foot">
|
|
202
|
+
<span class="rk-pill rk-pill-sky">Set per-hour & per-day spend caps</span>
|
|
203
|
+
<span class="rk-pill">Local <code>vidfarm serve</code> renders are free</span>
|
|
204
|
+
</div>
|
|
205
|
+
</section>
|
|
206
|
+
|
|
207
|
+
<!-- ── FAQ + trust ── -->
|
|
208
|
+
<section class="rk-pricing-faqs-wrap">
|
|
209
|
+
<div class="rk-pricing-faqs-head">
|
|
210
|
+
<span class="rk-eyebrow">Good to know</span>
|
|
211
|
+
<h2>Questions, answered</h2>
|
|
212
|
+
</div>
|
|
213
|
+
<div class="rk-grid rk-grid-2 rk-pricing-faqs">${faqCards}</div>
|
|
214
|
+
<div class="rk-row rk-wrap rk-pricing-trustrow">${trustPills}</div>
|
|
215
|
+
</section>
|
|
216
|
+
|
|
217
|
+
<!-- ── final gold CTA band ── -->
|
|
218
|
+
<section class="rk-pricing-cta">
|
|
219
|
+
<div class="rk-pricing-cta-art" aria-hidden="true"></div>
|
|
220
|
+
<div class="rk-pricing-cta-inner">
|
|
221
|
+
<span class="rk-badge rk-pricing-cta-badge">Ready when you are</span>
|
|
222
|
+
<h2 class="rk-pricing-cta-title">Make your first ad today.</h2>
|
|
223
|
+
<p class="rk-pricing-cta-sub">Fork a template, recut it with your footage, and render — free on your own machine. Upgrade only when you're ready to scale.</p>
|
|
224
|
+
<div class="rk-row rk-wrap rk-pricing-cta-btns">
|
|
225
|
+
<a class="rk-btn rk-btn-ink rk-btn-lg" href="#">Start free<span class="rk-arrow">→</span></a>
|
|
226
|
+
<a class="rk-btn rk-btn-ghost rk-btn-lg rk-pricing-cta-ghost" href="#">Book a demo</a>
|
|
227
|
+
</div>
|
|
228
|
+
</div>
|
|
229
|
+
</section>
|
|
230
|
+
|
|
231
|
+
</main>`;
|
|
232
|
+
const pageCss = `
|
|
233
|
+
.rk-pricing{padding-top:32px}
|
|
234
|
+
|
|
235
|
+
/* intro */
|
|
236
|
+
.rk-pricing-intro{display:grid;justify-items:center;text-align:center;gap:18px;max-width:760px;margin:8px auto 52px}
|
|
237
|
+
.rk-pricing-title{font-size:clamp(2.4rem,6vw,3.6rem);letter-spacing:-.035em;line-height:1.04}
|
|
238
|
+
.rk-pricing-title-accent{position:relative;display:inline-block;color:var(--rk-ink)}
|
|
239
|
+
.rk-pricing-title-accent::after{content:"";position:absolute;left:-2%;right:-2%;bottom:.08em;height:.36em;z-index:-1;
|
|
240
|
+
background:var(--rk-gold-500);border-radius:var(--rk-r-full);opacity:.55}
|
|
241
|
+
.rk-pricing-lede{font-size:var(--rk-text-lg);color:var(--rk-text-muted);max-width:620px;line-height:1.55}
|
|
242
|
+
.rk-pricing-toggle{display:inline-flex;gap:4px;padding:5px;background:#fff;border:1px solid var(--rk-border);
|
|
243
|
+
border-radius:var(--rk-r-full);box-shadow:var(--rk-shadow-sm)}
|
|
244
|
+
.rk-pricing-toggle-btn{display:inline-flex;align-items:center;gap:8px;padding:9px 20px;border:0;cursor:pointer;
|
|
245
|
+
background:transparent;border-radius:var(--rk-r-full);font-family:var(--rk-font-body);font-size:14px;
|
|
246
|
+
font-weight:600;color:var(--rk-n-600);transition:background var(--rk-dur) var(--rk-ease),color var(--rk-dur) var(--rk-ease)}
|
|
247
|
+
.rk-pricing-toggle-btn.is-active{background:var(--rk-ink);color:#fff}
|
|
248
|
+
.rk-pricing-save{font-size:11px;padding:2px 8px}
|
|
249
|
+
.rk-pricing-toggle-btn.is-active .rk-pricing-save{background:var(--rk-gold-500);color:var(--rk-ink)}
|
|
250
|
+
|
|
251
|
+
/* plan cards */
|
|
252
|
+
.rk-pricing-plans{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;align-items:start;margin-bottom:64px}
|
|
253
|
+
@media(max-width:960px){.rk-pricing-plans{grid-template-columns:1fr;max-width:460px;margin-left:auto;margin-right:auto}}
|
|
254
|
+
.rk-pricing-plan{position:relative;display:flex;flex-direction:column;gap:18px;overflow:visible}
|
|
255
|
+
.rk-pricing-plan-featured{border-color:transparent;box-shadow:var(--rk-ring-gold),var(--rk-shadow-xl);
|
|
256
|
+
background:linear-gradient(180deg,var(--rk-gold-tint) 0%,#fff 26%);transform:translateY(-10px);z-index:2}
|
|
257
|
+
@media(max-width:960px){.rk-pricing-plan-featured{transform:none}}
|
|
258
|
+
.rk-pricing-most{position:absolute;top:-14px;left:50%;transform:translateX(-50%);white-space:nowrap;
|
|
259
|
+
background:var(--rk-gold-500);color:var(--rk-ink);font-family:var(--rk-font-body);font-weight:700;
|
|
260
|
+
font-size:12px;letter-spacing:.02em;padding:6px 16px;border-radius:var(--rk-r-full);box-shadow:var(--rk-shadow-md)}
|
|
261
|
+
.rk-pricing-mono{font-family:var(--rk-font-display);font-weight:800;line-height:1}
|
|
262
|
+
.rk-pricing-plan-head{display:flex;align-items:center;gap:12px}
|
|
263
|
+
.rk-pricing-plan-head h3{font-size:var(--rk-text-2xl);margin-top:2px}
|
|
264
|
+
.rk-pricing-kicker-muted{color:var(--rk-n-500)}
|
|
265
|
+
.rk-pricing-price{display:flex;align-items:baseline;gap:2px;color:var(--rk-ink);margin-top:2px}
|
|
266
|
+
.rk-pricing-cur{font-family:var(--rk-font-display);font-weight:800;font-size:1.5rem;align-self:flex-start;margin-top:.5rem}
|
|
267
|
+
.rk-pricing-amount{font-family:var(--rk-font-display);font-weight:800;font-size:3.4rem;letter-spacing:-.03em;line-height:1}
|
|
268
|
+
.rk-pricing-suffix{font-size:var(--rk-text-base);font-weight:600;color:var(--rk-text-muted);margin-left:4px}
|
|
269
|
+
.rk-pricing-price-sub{font-size:13px;color:var(--rk-text-muted);min-height:18px}
|
|
270
|
+
.rk-strike{text-decoration:line-through;color:var(--rk-n-400)}
|
|
271
|
+
.rk-pricing-pitch{font-size:14px;color:var(--rk-text);line-height:1.55;min-height:66px}
|
|
272
|
+
.rk-pricing-feats{list-style:none;margin:0;padding:16px 0 0;display:grid;gap:12px;border-top:1px solid var(--rk-border)}
|
|
273
|
+
.rk-pricing-feat{display:flex;align-items:flex-start;gap:11px;font-size:14px;color:var(--rk-n-700)}
|
|
274
|
+
.rk-pricing-check{padding:6px}
|
|
275
|
+
.rk-pricing-check svg{width:100%;height:100%}
|
|
276
|
+
|
|
277
|
+
/* credit strip */
|
|
278
|
+
.rk-pricing-credits{padding:34px;background:linear-gradient(180deg,#fff 0%,var(--rk-n-50) 100%)}
|
|
279
|
+
.rk-pricing-credits-head{max-width:680px;margin-bottom:26px;display:grid;gap:8px}
|
|
280
|
+
.rk-pricing-credits-head h2{font-size:var(--rk-text-3xl);letter-spacing:-.02em}
|
|
281
|
+
.rk-pricing-credits-head p{font-size:15px;line-height:1.55}
|
|
282
|
+
.rk-pricing-packs{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
|
|
283
|
+
@media(max-width:900px){.rk-pricing-packs{grid-template-columns:repeat(2,1fr)}}
|
|
284
|
+
@media(max-width:520px){.rk-pricing-packs{grid-template-columns:1fr}}
|
|
285
|
+
.rk-pricing-pack{position:relative;display:flex;flex-direction:column;gap:10px;background:#fff;
|
|
286
|
+
border:1px solid var(--rk-border);border-radius:var(--rk-r-2xl);padding:20px 18px;box-shadow:var(--rk-shadow-xs);
|
|
287
|
+
transition:transform var(--rk-dur) var(--rk-ease),box-shadow var(--rk-dur) var(--rk-ease),border-color var(--rk-dur) var(--rk-ease)}
|
|
288
|
+
.rk-pricing-pack:hover{transform:translateY(-3px);box-shadow:var(--rk-shadow-md);border-color:var(--rk-border-strong)}
|
|
289
|
+
.rk-pricing-pack-popular{border-color:var(--rk-gold-500);box-shadow:0 0 0 2px var(--rk-gold-tint2),var(--rk-shadow-md)}
|
|
290
|
+
.rk-pricing-pack-flag{position:absolute;top:-11px;right:14px;font-size:11px;padding:3px 10px}
|
|
291
|
+
.rk-pricing-pack-top{display:flex;align-items:center;gap:9px}
|
|
292
|
+
.rk-pricing-pack-label{font-family:var(--rk-font-display);font-weight:700;font-size:14px;color:var(--rk-ink)}
|
|
293
|
+
.rk-pricing-pack-credits{font-family:var(--rk-font-display);font-weight:800;font-size:1.9rem;letter-spacing:-.02em;
|
|
294
|
+
color:var(--rk-ink);line-height:1;display:flex;align-items:baseline;gap:6px}
|
|
295
|
+
.rk-pricing-pack-credits span{font-family:var(--rk-font-body);font-size:12px;font-weight:600;color:var(--rk-text-muted);letter-spacing:0}
|
|
296
|
+
.rk-pricing-pack-bonus{align-self:flex-start}
|
|
297
|
+
.rk-pricing-pack-price{font-family:var(--rk-font-display);font-weight:700;font-size:1.05rem;color:var(--rk-n-700);
|
|
298
|
+
display:flex;align-items:baseline;gap:6px;margin-top:2px}
|
|
299
|
+
.rk-pricing-pack-price span{font-family:var(--rk-font-body);font-size:12px;font-weight:500;color:var(--rk-text-faint)}
|
|
300
|
+
.rk-pricing-pack-note{font-size:12px;color:var(--rk-text-muted);min-height:16px}
|
|
301
|
+
.rk-pricing-pack button{margin-top:4px}
|
|
302
|
+
.rk-pricing-credits-foot{display:flex;flex-wrap:wrap;gap:10px;margin-top:22px;padding-top:20px;border-top:1px solid var(--rk-border)}
|
|
303
|
+
|
|
304
|
+
/* faq + trust */
|
|
305
|
+
.rk-pricing-faqs-wrap{margin-top:64px}
|
|
306
|
+
.rk-pricing-faqs-head{display:grid;gap:8px;text-align:center;justify-items:center;margin-bottom:28px}
|
|
307
|
+
.rk-pricing-faqs-head h2{font-size:var(--rk-text-3xl);letter-spacing:-.02em}
|
|
308
|
+
.rk-pricing-faq{display:grid;gap:7px}
|
|
309
|
+
.rk-pricing-faq h3{font-size:var(--rk-text-base);font-weight:700}
|
|
310
|
+
.rk-pricing-faq p{font-size:14px;line-height:1.55}
|
|
311
|
+
.rk-pricing-trustrow{justify-content:center;margin-top:26px}
|
|
312
|
+
.rk-pricing-trust{background:#fff;border:1px solid var(--rk-border);box-shadow:var(--rk-shadow-xs);color:var(--rk-n-600);padding:7px 14px}
|
|
313
|
+
|
|
314
|
+
/* final gold CTA band */
|
|
315
|
+
.rk-pricing-cta{position:relative;overflow:hidden;margin-top:72px;border-radius:var(--rk-r-3xl);
|
|
316
|
+
padding:clamp(40px,6vw,64px) var(--rk-gutter);text-align:center;box-shadow:var(--rk-shadow-lg)}
|
|
317
|
+
.rk-pricing-cta-art{position:absolute;inset:0;z-index:0;background:
|
|
318
|
+
radial-gradient(70% 120% at 15% 10%,rgba(255,255,255,.7),transparent 55%),
|
|
319
|
+
radial-gradient(60% 120% at 90% 90%,rgba(252,185,0,.55),transparent 55%),
|
|
320
|
+
linear-gradient(135deg,var(--rk-gold-500) 0%,var(--rk-gold-600) 55%,#ffd873 100%)}
|
|
321
|
+
.rk-pricing-cta-inner{position:relative;z-index:1;display:grid;justify-items:center;gap:16px;max-width:620px;margin:0 auto}
|
|
322
|
+
.rk-pricing-cta-badge{background:rgba(255,255,255,.9);border-color:transparent}
|
|
323
|
+
.rk-pricing-cta-title{font-size:clamp(2rem,5vw,3rem);letter-spacing:-.03em;color:var(--rk-ink)}
|
|
324
|
+
.rk-pricing-cta-sub{font-size:var(--rk-text-lg);color:#5a4a12;line-height:1.5;font-weight:500}
|
|
325
|
+
.rk-pricing-cta-btns{justify-content:center;margin-top:8px}
|
|
326
|
+
.rk-pricing-cta-ghost{background:rgba(255,255,255,.85);border-color:transparent}
|
|
327
|
+
.rk-pricing-cta-ghost:hover{background:#fff}
|
|
328
|
+
`;
|
|
329
|
+
const script = `
|
|
330
|
+
(function(){
|
|
331
|
+
var root=document;
|
|
332
|
+
var btns=root.querySelectorAll('[data-rk-period]');
|
|
333
|
+
btns.forEach(function(btn){
|
|
334
|
+
btn.addEventListener('click',function(){
|
|
335
|
+
var period=btn.getAttribute('data-rk-period');
|
|
336
|
+
btns.forEach(function(b){b.classList.toggle('is-active',b===btn)});
|
|
337
|
+
var yearly=period==='yearly';
|
|
338
|
+
root.querySelectorAll('[data-rk-price]').forEach(function(el){
|
|
339
|
+
var v=el.getAttribute(yearly?'data-rk-yearly':'data-rk-monthly');
|
|
340
|
+
el.textContent=v;
|
|
341
|
+
});
|
|
342
|
+
root.querySelectorAll('[data-rk-price-note]').forEach(function(el){
|
|
343
|
+
el.style.visibility=yearly?'visible':'hidden';
|
|
344
|
+
});
|
|
345
|
+
});
|
|
346
|
+
});
|
|
347
|
+
// start on monthly: hide the "billed yearly" note until yearly is picked
|
|
348
|
+
root.querySelectorAll('[data-rk-price-note]').forEach(function(el){el.style.visibility='hidden';});
|
|
349
|
+
})();`;
|
|
350
|
+
return reskinDocument({
|
|
351
|
+
title: "vidfarm reskin — Pricing",
|
|
352
|
+
description: "Reskinned vidfarm pricing page — plans, credit wallet top-ups, and the $0.03/credit model.",
|
|
353
|
+
activeSlug: "pricing",
|
|
354
|
+
pageCss,
|
|
355
|
+
body,
|
|
356
|
+
script
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
//# sourceMappingURL=pricing-page.js.map
|