@mevdragon/vidfarm-devcli 0.17.0 → 0.18.1
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/vidfarm-media/SKILL.md +43 -6
- package/SKILL.director.md +37 -23
- package/SKILL.platform.md +6 -6
- package/demo/dist/app.js +69 -69
- package/demo/dist/favicon.ico +0 -0
- package/dist/src/app.js +1832 -213
- package/dist/src/cli.js +238 -17
- package/dist/src/devcli/clip-store.js +29 -2
- package/dist/src/devcli/clips.js +116 -73
- package/dist/src/devcli/composition-edit.js +262 -0
- package/dist/src/devcli/timeline-edit.js +283 -0
- package/dist/src/editor-chat.js +29 -6
- package/dist/src/frontend/discover-client.js +130 -0
- package/dist/src/frontend/discover-store.js +23 -0
- package/dist/src/frontend/file-directory.js +744 -0
- package/dist/src/frontend/template-editor-chat.js +22 -19
- package/dist/src/landing-page.js +24 -7
- package/dist/src/page-shell.js +25 -1
- package/dist/src/reskin/agency-page.js +214 -170
- package/dist/src/reskin/calendar-page.js +503 -187
- package/dist/src/reskin/chat-page.js +739 -299
- package/dist/src/reskin/discover-page.js +1450 -279
- package/dist/src/reskin/document.js +1392 -16
- package/dist/src/reskin/help-page.js +139 -100
- package/dist/src/reskin/index-page.js +1 -1
- package/dist/src/reskin/inpaint-page.js +547 -0
- package/dist/src/reskin/job-runs-page.js +355 -127
- package/dist/src/reskin/library-page.js +1188 -317
- package/dist/src/reskin/login-page.js +124 -87
- package/dist/src/reskin/pricing-page.js +197 -166
- package/dist/src/reskin/settings-page.js +566 -187
- package/dist/src/reskin/theme.js +434 -17
- package/dist/src/services/clip-curation/gemini.js +5 -0
- package/dist/src/services/clip-curation/hunt.js +79 -1
- package/dist/src/services/clip-curation/index.js +2 -1
- package/dist/src/services/clip-curation/local-agent.js +4 -3
- package/dist/src/services/clip-curation/media-select.js +85 -0
- package/dist/src/services/clip-curation/query.js +5 -1
- package/dist/src/services/clip-curation/refine.js +50 -20
- package/dist/src/services/clip-curation/scan.js +10 -3
- package/dist/src/services/clip-curation/taxonomy.js +3 -1
- package/dist/src/services/clip-curation/taxonomy.v1.json +13 -1
- package/dist/src/services/clip-records.js +14 -1
- package/dist/src/services/clip-search.js +43 -13
- package/dist/src/services/file-directory.js +114 -0
- package/dist/src/services/storage.js +24 -1
- package/dist/src/services/upstream.js +5 -5
- package/dist/src/template-editor-shell.js +16 -2
- package/package.json +1 -1
- package/public/assets/discover-client-app.js +1 -0
- package/public/assets/file-directory-app.js +2 -0
- package/public/assets/homepage-client-app.js +12 -12
- package/public/assets/page-runtime-client-app.js +24 -24
- package/src/assets/favicon.ico +0 -0
- package/src/assets/logo-vidfarm.png +0 -0
|
@@ -1,127 +1,173 @@
|
|
|
1
|
-
// /reskin/pricing —
|
|
2
|
-
// warm-sunny design system using ONLY shared rk-* primitives + a page-scoped
|
|
3
|
-
// rk-pricing-* CSS block + a small self-contained module script.
|
|
1
|
+
// /reskin/pricing — MIGRATED to real production billing.
|
|
4
2
|
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
// the
|
|
3
|
+
// This mirrors the live vidfarm billing surface (src/account-pages-legacy.ts
|
|
4
|
+
// `renderPricingPage` + the settings wallet flow + the help page). It accepts the
|
|
5
|
+
// SAME input the live route builds (`Parameters<typeof renderPricingPage>[0]` =
|
|
6
|
+
// `{ email }`), which the live app renders post-login as a paywall gate
|
|
7
|
+
// ("Paid plan required — {email} does not have an active plan").
|
|
8
|
+
//
|
|
9
|
+
// REAL facts wired here (nothing invented):
|
|
10
|
+
// • The one real subscription tier is **$99/month** (the live "Current Offer").
|
|
11
|
+
// On the live page the Buy button is DISABLED ("Checkout is not enabled yet"),
|
|
12
|
+
// so activation happens by contacting operator@zoom-gtm.com — that is the real
|
|
13
|
+
// path today, so the Pro CTA is that mailto (email pre-filled).
|
|
14
|
+
// • Local `vidfarm serve` renders are free → the real free tier.
|
|
15
|
+
// • The credit wallet: every credit is $0.03 of compute; top-ups go to the REAL
|
|
16
|
+
// Stripe checkout https://buy.stripe.com/3cIfZggERgLsfVzfKR53O0H with the
|
|
17
|
+
// email pre-filled (exactly the URL + prefill the live settings modal uses).
|
|
18
|
+
// • Manage/cancel the subscription via the REAL Stripe billing portal
|
|
19
|
+
// https://billing.stripe.com/p/login/fZecQubkxcwOgDuaEE ; 90-day refunds via
|
|
20
|
+
// operator@zoom-gtm.com — both straight from the live help page.
|
|
21
|
+
// The gold "joy" accent is reserved for the hero plan + the primary CTAs; every
|
|
22
|
+
// other action uses the charcoal/ghost workhorses. ✓ feature checkmarks kept.
|
|
14
23
|
import { reskinDocument, rkEscape } from "./document.js";
|
|
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
|
-
|
|
24
|
+
// ── real production constants (copied from the live app) ──
|
|
25
|
+
const SUPPORT_EMAIL = "operator@zoom-gtm.com";
|
|
26
|
+
const WALLET_CHECKOUT_BASE = "https://buy.stripe.com/3cIfZggERgLsfVzfKR53O0H";
|
|
27
|
+
const BILLING_PORTAL_URL = "https://billing.stripe.com/p/login/fZecQubkxcwOgDuaEE";
|
|
28
|
+
const PLAN_PRICE_USD = 99;
|
|
29
|
+
const CREDIT_USD = 0.03;
|
|
30
|
+
/** Real wallet top-up: the live Stripe checkout with the email pre-filled (the
|
|
31
|
+
* live settings modal also registers a server-side client_reference_id; a static
|
|
32
|
+
* pricing page can't, so it links to the same checkout with the email prefill).
|
|
33
|
+
* Email may be empty (the route currently passes none) — then no prefill param. */
|
|
34
|
+
function walletCheckoutUrl(email) {
|
|
35
|
+
return email
|
|
36
|
+
? `${WALLET_CHECKOUT_BASE}?prefilled_email=${encodeURIComponent(email)}`
|
|
37
|
+
: WALLET_CHECKOUT_BASE;
|
|
38
|
+
}
|
|
39
|
+
function mailto(email, subject, bodyLead) {
|
|
40
|
+
const body = email ? `${bodyLead} My account email: ${email}` : bodyLead;
|
|
41
|
+
return `mailto:${SUPPORT_EMAIL}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
|
|
42
|
+
}
|
|
43
|
+
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>`;
|
|
44
|
+
function usd(n) {
|
|
45
|
+
return `$${n.toLocaleString("en-US")}`;
|
|
46
|
+
}
|
|
47
|
+
function credits(n) {
|
|
48
|
+
return n.toLocaleString("en-US");
|
|
49
|
+
}
|
|
50
|
+
function creditsForUsd(n) {
|
|
51
|
+
return Math.floor(n / CREDIT_USD);
|
|
52
|
+
}
|
|
53
|
+
function buildPlans(email) {
|
|
54
|
+
return [
|
|
55
|
+
{
|
|
56
|
+
id: "local",
|
|
57
|
+
kicker: "Get started",
|
|
58
|
+
name: "Local",
|
|
59
|
+
price: { kind: "free", sub: "forever · vidfarm serve" },
|
|
60
|
+
pitch: "Fork templates, recut with your own footage, and render in-process on your own machine — no card required.",
|
|
61
|
+
features: [
|
|
62
|
+
"Local in-process renders (free)",
|
|
63
|
+
"Fork & recut the community feed",
|
|
64
|
+
"Bring your own AI keys",
|
|
65
|
+
"Clip library & My Files",
|
|
66
|
+
"1 publishing channel"
|
|
67
|
+
],
|
|
68
|
+
ctaLabel: "Start free",
|
|
69
|
+
ctaHref: "/login",
|
|
70
|
+
ctaStyle: "ghost"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
id: "pro",
|
|
74
|
+
kicker: "Full access",
|
|
75
|
+
name: "Pro",
|
|
76
|
+
price: { kind: "monthly", usd: PLAN_PRICE_USD, sub: "Billed monthly · cancel anytime · 90-day money-back" },
|
|
77
|
+
pitch: "For operators publishing consistently — unlimited cloud output, Swipe-mode auto-recut, and every publishing channel.",
|
|
78
|
+
features: [
|
|
79
|
+
"Everything in Local",
|
|
80
|
+
"Unlimited cloud renders",
|
|
81
|
+
"Swipe mode & AI recaption",
|
|
82
|
+
"FlockPoster + email channels",
|
|
83
|
+
"Wallet top-ups at $0.03 / credit",
|
|
84
|
+
"Email support"
|
|
85
|
+
],
|
|
86
|
+
ctaLabel: "Get access",
|
|
87
|
+
ctaHref: mailto(email, "Activate my Vidfarm Pro plan", "I'd like to activate the $99/mo Vidfarm Pro plan."),
|
|
88
|
+
ctaStyle: "gold",
|
|
89
|
+
featured: true
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
id: "agency",
|
|
93
|
+
kicker: "For teams",
|
|
94
|
+
name: "Agency",
|
|
95
|
+
price: { kind: "custom", label: "Custom", sub: "Priced per workspace" },
|
|
96
|
+
pitch: "For studios running many clients — separate client workspaces, per-client keys and wallets, and hands-on onboarding.",
|
|
97
|
+
features: [
|
|
98
|
+
"Multiple client workspaces",
|
|
99
|
+
"Per-client AI keys & wallets",
|
|
100
|
+
"Team seats",
|
|
101
|
+
"Shared credit billing",
|
|
102
|
+
"Hands-on onboarding"
|
|
103
|
+
],
|
|
104
|
+
ctaLabel: "Talk to sales",
|
|
105
|
+
ctaHref: mailto(email, "Vidfarm for agencies", "I'd like to talk about Vidfarm agency workspaces."),
|
|
106
|
+
ctaStyle: "ink"
|
|
107
|
+
}
|
|
108
|
+
];
|
|
109
|
+
}
|
|
110
|
+
// Example top-up amounts. Credit counts are the HONEST $0.03/credit math — no
|
|
111
|
+
// invented bonus tiers. Each links to the same real Stripe checkout (the amount
|
|
112
|
+
// is confirmed on Stripe's hosted page).
|
|
113
|
+
const CREDIT_EXAMPLES = [
|
|
114
|
+
{ usd: 20 },
|
|
115
|
+
{ usd: 50, recommended: true },
|
|
116
|
+
{ usd: 100 },
|
|
117
|
+
{ usd: 250 }
|
|
79
118
|
];
|
|
80
119
|
const FAQS = [
|
|
81
120
|
{
|
|
82
121
|
q: "What exactly is a credit?",
|
|
83
|
-
a: "A credit is $0.03 of compute.
|
|
122
|
+
a: "A credit is $0.03 of compute. Cloud renders, clip scans, and decompose passes draw from your wallet. Bring-your-own AI keys are never billed by vidfarm — you only pay for compute you actually run."
|
|
84
123
|
},
|
|
85
124
|
{
|
|
86
125
|
q: "Do credits expire?",
|
|
87
|
-
a: "No. Wallet credits roll over forever and the balance auto-scales to zero —
|
|
126
|
+
a: "No. Wallet credits roll over forever and the balance auto-scales to zero — nothing is charged while you're idle."
|
|
88
127
|
},
|
|
89
128
|
{
|
|
90
129
|
q: "Can I set spend limits?",
|
|
91
130
|
a: "Yes. Cap usage with per-hour and per-day credit rate limits so long-lived render jobs never surprise you."
|
|
92
131
|
},
|
|
93
132
|
{
|
|
94
|
-
q: "
|
|
95
|
-
a: "Yep. A vidfarm serve box renders in-process on your machine
|
|
133
|
+
q: "Are local renders really free?",
|
|
134
|
+
a: "Yep. A vidfarm serve box renders in-process on your own machine at no charge — perfect for reusing already-decomposed templates."
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
q: "How do I start the $99 / mo plan?",
|
|
138
|
+
a: `Self-serve subscription checkout is rolling out. To activate the Pro plan today, email ${SUPPORT_EMAIL} from your account address and we'll switch it on.`
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
q: "Can I cancel or get a refund?",
|
|
142
|
+
a: `Cancel anytime in the Stripe billing portal. We also offer 90-day refunds — email ${SUPPORT_EMAIL} and mention the address you used at Stripe checkout so we can find your subscription quickly.`
|
|
96
143
|
}
|
|
97
144
|
];
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
|
|
145
|
+
function priceBlock(p) {
|
|
146
|
+
if (p.price.kind === "free") {
|
|
147
|
+
return `<div class="rk-pricing-price"><span class="rk-pricing-amount">Free</span></div>
|
|
148
|
+
<p class="rk-pricing-price-sub">${rkEscape(p.price.sub)}</p>`;
|
|
149
|
+
}
|
|
150
|
+
if (p.price.kind === "custom") {
|
|
151
|
+
return `<div class="rk-pricing-price"><span class="rk-pricing-amount rk-pricing-amount-sm">${rkEscape(p.price.label ?? "Custom")}</span></div>
|
|
152
|
+
<p class="rk-pricing-price-sub">${rkEscape(p.price.sub)}</p>`;
|
|
153
|
+
}
|
|
154
|
+
return `<div class="rk-pricing-price">
|
|
155
|
+
<span class="rk-pricing-cur">$</span>
|
|
156
|
+
<span class="rk-pricing-amount">${p.price.usd}</span>
|
|
157
|
+
<span class="rk-pricing-suffix">/mo</span>
|
|
158
|
+
</div>
|
|
159
|
+
<p class="rk-pricing-price-sub">${rkEscape(p.price.sub)}</p>`;
|
|
104
160
|
}
|
|
105
161
|
function planCard(p) {
|
|
106
162
|
const featured = p.featured ? " rk-pricing-plan-featured" : "";
|
|
107
|
-
const badge = p.featured
|
|
108
|
-
? `<span class="rk-pricing-most">Most popular</span>`
|
|
109
|
-
: "";
|
|
163
|
+
const badge = p.featured ? `<span class="rk-pricing-most">Most popular</span>` : "";
|
|
110
164
|
const checkTint = p.featured ? "rk-tile-gold" : "rk-tile-green";
|
|
111
165
|
const features = p.features.map((f) => `
|
|
112
166
|
<li class="rk-pricing-feat">
|
|
113
167
|
<span class="rk-tile rk-tile-sm ${checkTint} rk-pricing-check">${CHECK}</span>
|
|
114
168
|
<span>${rkEscape(f)}</span>
|
|
115
169
|
</li>`).join("");
|
|
116
|
-
const
|
|
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>`;
|
|
170
|
+
const ext = p.ctaExternal ? ` target="_blank" rel="noreferrer"` : "";
|
|
125
171
|
return `
|
|
126
172
|
<article class="rk-card rk-card-hover rk-pricing-plan${featured}">
|
|
127
173
|
${badge}
|
|
@@ -132,36 +178,37 @@ function planCard(p) {
|
|
|
132
178
|
<h3>${rkEscape(p.name)}</h3>
|
|
133
179
|
</div>
|
|
134
180
|
</div>
|
|
135
|
-
${priceBlock}
|
|
181
|
+
${priceBlock(p)}
|
|
136
182
|
<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="
|
|
183
|
+
<a class="rk-btn rk-btn-${p.ctaStyle} rk-btn-block rk-btn-lg" href="${rkEscape(p.ctaHref)}"${ext}>${rkEscape(p.ctaLabel)}<span class="rk-arrow">→</span></a>
|
|
138
184
|
<ul class="rk-pricing-feats">${features}</ul>
|
|
139
185
|
</article>`;
|
|
140
186
|
}
|
|
141
|
-
function packCard(
|
|
142
|
-
const total =
|
|
143
|
-
const popular =
|
|
144
|
-
const flag =
|
|
145
|
-
const
|
|
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>`;
|
|
187
|
+
function packCard(email, pack) {
|
|
188
|
+
const total = creditsForUsd(pack.usd);
|
|
189
|
+
const popular = pack.recommended ? " rk-pricing-pack-popular" : "";
|
|
190
|
+
const flag = pack.recommended ? `<span class="rk-pill rk-pill-gold rk-pricing-pack-flag">Recommended</span>` : "";
|
|
191
|
+
const checkoutUrl = walletCheckoutUrl(email);
|
|
148
192
|
return `
|
|
149
193
|
<article class="rk-pricing-pack${popular}">
|
|
150
194
|
${flag}
|
|
151
195
|
<div class="rk-pricing-pack-top">
|
|
152
|
-
<span class="rk-tile rk-tile-sm ${
|
|
153
|
-
<span class="rk-pricing-pack-label">${rkEscape(
|
|
196
|
+
<span class="rk-tile rk-tile-sm ${pack.recommended ? "rk-tile-gold" : "rk-tile-coral"} rk-pricing-mono" aria-hidden="true">${rkEscape(usd(pack.usd).charAt(0))}</span>
|
|
197
|
+
<span class="rk-pricing-pack-label">${rkEscape(usd(pack.usd))} top-up</span>
|
|
154
198
|
</div>
|
|
155
199
|
<div class="rk-pricing-pack-credits">${credits(total)}<span>credits</span></div>
|
|
156
|
-
$
|
|
157
|
-
<
|
|
158
|
-
<
|
|
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>
|
|
200
|
+
<span class="rk-pill rk-pricing-pack-bonus">at $0.03 / credit</span>
|
|
201
|
+
<p class="rk-pricing-pack-note">Credits never expire · roll over forever</p>
|
|
202
|
+
<a class="rk-btn ${pack.recommended ? "rk-btn-gold" : "rk-btn-ghost"} rk-btn-block rk-btn-sm" href="${rkEscape(checkoutUrl)}" target="_blank" rel="noreferrer">Top up ${rkEscape(usd(pack.usd))}</a>
|
|
160
203
|
</article>`;
|
|
161
204
|
}
|
|
162
|
-
export function renderReskinPricing() {
|
|
163
|
-
|
|
164
|
-
|
|
205
|
+
export function renderReskinPricing(input) {
|
|
206
|
+
// Runtime-safe: the live route renders this post-login with the customer email;
|
|
207
|
+
// if none is supplied, email-specific bits degrade gracefully (no prefill).
|
|
208
|
+
const email = (input?.email ?? "").trim();
|
|
209
|
+
const planCards = buildPlans(email).map(planCard).join("");
|
|
210
|
+
const packCards = CREDIT_EXAMPLES.map((p) => packCard(email, p)).join("");
|
|
211
|
+
const checkoutUrl = walletCheckoutUrl(email);
|
|
165
212
|
const faqCards = FAQS.map((f) => `
|
|
166
213
|
<div class="rk-card rk-card-pad-sm rk-pricing-faq">
|
|
167
214
|
<h3>${rkEscape(f.q)}</h3>
|
|
@@ -171,36 +218,42 @@ export function renderReskinPricing() {
|
|
|
171
218
|
"Cancel anytime",
|
|
172
219
|
"Transparent per-render billing",
|
|
173
220
|
"BYO AI keys — never billed",
|
|
174
|
-
"
|
|
175
|
-
].map((t) => `<span class="rk-pill rk-pricing-trust">${t}</span>`).join("");
|
|
221
|
+
"90-day money-back"
|
|
222
|
+
].map((t) => `<span class="rk-pill rk-pricing-trust">${rkEscape(t)}</span>`).join("");
|
|
223
|
+
const demoHref = mailto(email, "Vidfarm demo", "I'd like a Vidfarm demo.");
|
|
176
224
|
const body = `
|
|
177
225
|
<main class="rk-container rk-page rk-pricing">
|
|
178
226
|
|
|
179
227
|
<!-- ── intro ── -->
|
|
180
228
|
<section class="rk-pricing-intro">
|
|
181
|
-
<span class="rk-badge">Simple, sunny pricing</span>
|
|
182
229
|
<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.
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
</div>
|
|
230
|
+
<p class="rk-pricing-lede">Start free and render locally. Go Pro for unlimited cloud output. Top up a credit wallet for compute — only ever pay for what you render.</p>
|
|
231
|
+
${email
|
|
232
|
+
? `<p class="rk-pricing-signed">Signed in as <strong>${rkEscape(email)}</strong> — no active plan yet. Pick one below to unlock cloud rendering.</p>`
|
|
233
|
+
: ""}
|
|
188
234
|
</section>
|
|
189
235
|
|
|
190
236
|
<!-- ── plan cards ── -->
|
|
191
237
|
<section class="rk-pricing-plans">${planCards}</section>
|
|
192
238
|
|
|
239
|
+
<p class="rk-pricing-manage">Already on a plan? <a href="${rkEscape(BILLING_PORTAL_URL)}" target="_blank" rel="noreferrer">Manage billing, invoices & cancellation in the Stripe portal <span class="rk-arrow">↗</span></a></p>
|
|
240
|
+
|
|
193
241
|
<!-- ── credit top-up strip ── -->
|
|
194
242
|
<section class="rk-card rk-pricing-credits">
|
|
195
243
|
<div class="rk-pricing-credits-head">
|
|
196
244
|
<span class="rk-eyebrow">Credit wallet</span>
|
|
197
245
|
<h2>Top up credits, pay only for compute</h2>
|
|
198
246
|
<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>
|
|
247
|
+
<div class="rk-row rk-wrap rk-pricing-credits-cta">
|
|
248
|
+
<a class="rk-btn rk-btn-gold rk-btn-lg" href="${rkEscape(checkoutUrl)}" target="_blank" rel="noreferrer">Top up wallet<span class="rk-arrow">→</span></a>
|
|
249
|
+
<span class="rk-hint">Secure Stripe checkout${email ? ` · pre-filled for ${rkEscape(email)}` : ""}</span>
|
|
250
|
+
</div>
|
|
199
251
|
</div>
|
|
200
252
|
<div class="rk-pricing-packs">${packCards}</div>
|
|
201
253
|
<div class="rk-pricing-credits-foot">
|
|
202
|
-
<span class="rk-pill rk-pill-sky">Set per-hour & per-day spend caps</span>
|
|
254
|
+
<span class="rk-pill rk-pill-sky">Set per-hour & per-day spend caps</span>
|
|
203
255
|
<span class="rk-pill">Local <code>vidfarm serve</code> renders are free</span>
|
|
256
|
+
<span class="rk-pill">Choose any amount at checkout</span>
|
|
204
257
|
</div>
|
|
205
258
|
</section>
|
|
206
259
|
|
|
@@ -220,10 +273,10 @@ export function renderReskinPricing() {
|
|
|
220
273
|
<div class="rk-pricing-cta-inner">
|
|
221
274
|
<span class="rk-badge rk-pricing-cta-badge">Ready when you are</span>
|
|
222
275
|
<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.
|
|
276
|
+
<p class="rk-pricing-cta-sub">Fork a template, recut it with your footage, and render — free on your own machine. Go Pro only when you're ready to scale.</p>
|
|
224
277
|
<div class="rk-row rk-wrap rk-pricing-cta-btns">
|
|
225
|
-
<a class="rk-btn rk-btn-ink rk-btn-lg" href="
|
|
226
|
-
<a class="rk-btn rk-btn-ghost rk-btn-lg rk-pricing-cta-ghost" href="
|
|
278
|
+
<a class="rk-btn rk-btn-ink rk-btn-lg" href="/login">Start free<span class="rk-arrow">→</span></a>
|
|
279
|
+
<a class="rk-btn rk-btn-ghost rk-btn-lg rk-pricing-cta-ghost" href="${rkEscape(demoHref)}">Book a demo</a>
|
|
227
280
|
</div>
|
|
228
281
|
</div>
|
|
229
282
|
</section>
|
|
@@ -239,17 +292,12 @@ export function renderReskinPricing() {
|
|
|
239
292
|
.rk-pricing-title-accent::after{content:"";position:absolute;left:-2%;right:-2%;bottom:.08em;height:.36em;z-index:-1;
|
|
240
293
|
background:var(--rk-gold-500);border-radius:var(--rk-r-full);opacity:.55}
|
|
241
294
|
.rk-pricing-lede{font-size:var(--rk-text-lg);color:var(--rk-text-muted);max-width:620px;line-height:1.55}
|
|
242
|
-
.rk-pricing-
|
|
243
|
-
border-radius:var(--rk-r-full)
|
|
244
|
-
.rk-pricing-
|
|
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)}
|
|
295
|
+
.rk-pricing-signed{font-size:13px;color:var(--rk-n-600);background:var(--rk-gold-tint);border:1px solid var(--rk-gold-tint2);
|
|
296
|
+
padding:8px 16px;border-radius:var(--rk-r-full)}
|
|
297
|
+
.rk-pricing-signed strong{color:var(--rk-ink);font-weight:700}
|
|
250
298
|
|
|
251
299
|
/* plan cards */
|
|
252
|
-
.rk-pricing-plans{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;align-items:start;margin-bottom:
|
|
300
|
+
.rk-pricing-plans{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;align-items:start;margin-bottom:20px}
|
|
253
301
|
@media(max-width:960px){.rk-pricing-plans{grid-template-columns:1fr;max-width:460px;margin-left:auto;margin-right:auto}}
|
|
254
302
|
.rk-pricing-plan{position:relative;display:flex;flex-direction:column;gap:18px;overflow:visible}
|
|
255
303
|
.rk-pricing-plan-featured{border-color:transparent;box-shadow:var(--rk-ring-gold),var(--rk-shadow-xl);
|
|
@@ -265,20 +313,27 @@ export function renderReskinPricing() {
|
|
|
265
313
|
.rk-pricing-price{display:flex;align-items:baseline;gap:2px;color:var(--rk-ink);margin-top:2px}
|
|
266
314
|
.rk-pricing-cur{font-family:var(--rk-font-display);font-weight:800;font-size:1.5rem;align-self:flex-start;margin-top:.5rem}
|
|
267
315
|
.rk-pricing-amount{font-family:var(--rk-font-display);font-weight:800;font-size:3.4rem;letter-spacing:-.03em;line-height:1}
|
|
316
|
+
.rk-pricing-amount-sm{font-size:2.5rem}
|
|
268
317
|
.rk-pricing-suffix{font-size:var(--rk-text-base);font-weight:600;color:var(--rk-text-muted);margin-left:4px}
|
|
269
318
|
.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
319
|
.rk-pricing-pitch{font-size:14px;color:var(--rk-text);line-height:1.55;min-height:66px}
|
|
272
320
|
.rk-pricing-feats{list-style:none;margin:0;padding:16px 0 0;display:grid;gap:12px;border-top:1px solid var(--rk-border)}
|
|
273
321
|
.rk-pricing-feat{display:flex;align-items:flex-start;gap:11px;font-size:14px;color:var(--rk-n-700)}
|
|
274
322
|
.rk-pricing-check{padding:6px}
|
|
275
323
|
.rk-pricing-check svg{width:100%;height:100%}
|
|
276
324
|
|
|
325
|
+
/* manage-billing line */
|
|
326
|
+
.rk-pricing-manage{text-align:center;font-size:13px;color:var(--rk-text-muted);margin:0 auto 60px}
|
|
327
|
+
.rk-pricing-manage a{color:var(--rk-n-700);font-weight:600;border-bottom:1px solid var(--rk-border-strong)}
|
|
328
|
+
.rk-pricing-manage a:hover{color:var(--rk-ink)}
|
|
329
|
+
|
|
277
330
|
/* credit strip */
|
|
278
331
|
.rk-pricing-credits{padding:34px;background:linear-gradient(180deg,#fff 0%,var(--rk-n-50) 100%)}
|
|
332
|
+
@media(max-width:560px){.rk-pricing-credits{padding:22px 16px}}
|
|
279
333
|
.rk-pricing-credits-head{max-width:680px;margin-bottom:26px;display:grid;gap:8px}
|
|
280
334
|
.rk-pricing-credits-head h2{font-size:var(--rk-text-3xl);letter-spacing:-.02em}
|
|
281
335
|
.rk-pricing-credits-head p{font-size:15px;line-height:1.55}
|
|
336
|
+
.rk-pricing-credits-cta{margin-top:8px}
|
|
282
337
|
.rk-pricing-packs{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
|
|
283
338
|
@media(max-width:900px){.rk-pricing-packs{grid-template-columns:repeat(2,1fr)}}
|
|
284
339
|
@media(max-width:520px){.rk-pricing-packs{grid-template-columns:1fr}}
|
|
@@ -294,11 +349,8 @@ export function renderReskinPricing() {
|
|
|
294
349
|
color:var(--rk-ink);line-height:1;display:flex;align-items:baseline;gap:6px}
|
|
295
350
|
.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
351
|
.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
352
|
.rk-pricing-pack-note{font-size:12px;color:var(--rk-text-muted);min-height:16px}
|
|
301
|
-
.rk-pricing-pack
|
|
353
|
+
.rk-pricing-pack a{margin-top:4px}
|
|
302
354
|
.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
355
|
|
|
304
356
|
/* faq + trust */
|
|
@@ -326,34 +378,13 @@ export function renderReskinPricing() {
|
|
|
326
378
|
.rk-pricing-cta-ghost{background:rgba(255,255,255,.85);border-color:transparent}
|
|
327
379
|
.rk-pricing-cta-ghost:hover{background:#fff}
|
|
328
380
|
`;
|
|
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
381
|
return reskinDocument({
|
|
351
382
|
title: "vidfarm reskin — Pricing",
|
|
352
|
-
description: "Reskinned vidfarm pricing
|
|
383
|
+
description: "Reskinned vidfarm pricing — the $99/mo Pro plan, the $0.03/credit wallet, and real Stripe checkout.",
|
|
353
384
|
activeSlug: "pricing",
|
|
385
|
+
account: { email: input.email },
|
|
354
386
|
pageCss,
|
|
355
|
-
body
|
|
356
|
-
script
|
|
387
|
+
body
|
|
357
388
|
});
|
|
358
389
|
}
|
|
359
390
|
//# sourceMappingURL=pricing-page.js.map
|