@mevdragon/vidfarm-devcli 0.16.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/dist/src/account-pages-legacy.js +2 -2
- package/dist/src/app.js +441 -77
- package/dist/src/editor-chat.js +2 -2
- package/dist/src/frontend/homepage-client.js +162 -2
- package/dist/src/frontend/homepage-store.js +30 -1
- package/dist/src/frontend/homepage-view.js +111 -4
- package/dist/src/homepage.js +184 -1
- 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 +54 -0
- package/dist/src/services/swipe-customize.js +434 -0
- package/package.json +1 -1
- package/public/assets/homepage-client-app.js +22 -22
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
// /reskin/settings — the flagship reskin. Reference implementation for the
|
|
2
|
+
// migration: shows how to port a real vidfarm page (the 4-tab Settings screen)
|
|
3
|
+
// into the farmville design system using ONLY shared rk-* primitives + a small
|
|
4
|
+
// page-scoped CSS block + a self-contained module script.
|
|
5
|
+
//
|
|
6
|
+
// Renders with representative SAMPLE data so it can be viewed without auth. All
|
|
7
|
+
// forms post to the REAL /settings/* endpoints, so the shape stays honest.
|
|
8
|
+
// Faithfully mirrors src/account-pages-legacy.ts → renderSettingsPage:
|
|
9
|
+
// Profile (display name, about, attachments) · Wallet (balance, ledger) ·
|
|
10
|
+
// Channels (email + FlockPoster) · Developer (vidfarm key, AI provider keys).
|
|
11
|
+
import { reskinDocument, rkEscape } from "./document.js";
|
|
12
|
+
const SAMPLE = {
|
|
13
|
+
name: "Dylan Vane",
|
|
14
|
+
email: "dylan@studio.co",
|
|
15
|
+
accountId: "acct_8f2a10",
|
|
16
|
+
isPaidPlan: true,
|
|
17
|
+
about: "Vidfarm makes short-form ads for DTC brands. Punchy hooks, UGC energy, captions that pop. Audience: founders & marketers who want to ship a week of content in an afternoon.",
|
|
18
|
+
vidfarmApiKey: "vf_live_9c41f0b7a2e84d6f8b3c9a1e",
|
|
19
|
+
wallet: { balanceUsd: 12.4, totalFundsAddedUsd: 40, totalChargeUsd: 27.6, updatedAt: "Jul 7, 2026, 4:12 PM" },
|
|
20
|
+
walletEvents: [
|
|
21
|
+
{ title: "Wallet top-up", sub: "Visa ···· 4242", amountUsd: 20, when: "Jul 6", kind: "credit" },
|
|
22
|
+
{ title: "Timeline render usage", sub: "HyperFrames Lambda · job_a91f", amountUsd: -1.8, when: "Jul 6", kind: "debit" },
|
|
23
|
+
{ title: "Clip scan usage", sub: "clip_scan_lambda · 14 clips", amountUsd: -0.42, when: "Jul 5", kind: "debit" },
|
|
24
|
+
{ title: "Timeline render usage", sub: "HyperFrames Lambda · job_77c2", amountUsd: -2.1, when: "Jul 4", kind: "debit" },
|
|
25
|
+
{ title: "Wallet top-up", sub: "Visa ···· 4242", amountUsd: 20, when: "Jul 1", kind: "credit" }
|
|
26
|
+
],
|
|
27
|
+
attachments: [
|
|
28
|
+
{ fileName: "brand-guidelines.pdf", kind: "PDF", size: "2.4 MB", when: "Jul 2" },
|
|
29
|
+
{ fileName: "logo-lockup.png", kind: "PNG", size: "184 KB", when: "Jul 2" },
|
|
30
|
+
{ fileName: "founder-vo-sample.mp3", kind: "Audio", size: "1.1 MB", when: "Jun 28" }
|
|
31
|
+
],
|
|
32
|
+
channels: [
|
|
33
|
+
{ title: "Vidfarm Daily", platform: "TikTok", handle: "@vidfarm", status: "Connected", kind: "flockposter" },
|
|
34
|
+
{ title: "Founder Reels", platform: "Instagram", handle: "@dylan.builds", status: "Connected", kind: "flockposter" },
|
|
35
|
+
{ title: "Newsletter drop", platform: "Email", handle: "dylan@studio.co", status: "Verify sent", kind: "email" }
|
|
36
|
+
],
|
|
37
|
+
providerKeys: [
|
|
38
|
+
{ provider: "OpenAI", label: "gpt-5.4 workspace", secret: "sk-proj-1a2b3c4d5e6f7g8h9i0j", status: "Active", lastUsed: "2h ago" },
|
|
39
|
+
{ provider: "Gemini", label: "clip tagging", secret: "AIzaSyD-9x0q1w2e3r4t5y6u7i8o", status: "Active", lastUsed: "yesterday" }
|
|
40
|
+
]
|
|
41
|
+
};
|
|
42
|
+
const EYE = `<svg width="16" height="16" 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>`;
|
|
43
|
+
function money(n) {
|
|
44
|
+
const abs = Math.abs(n).toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
45
|
+
return `${n < 0 ? "−" : ""}$${abs}`;
|
|
46
|
+
}
|
|
47
|
+
function tabButton(slug, label, active) {
|
|
48
|
+
return `<button type="button" class="rk-side-item${active ? " is-active" : ""}" data-rk-tab="${slug}">${label}</button>`;
|
|
49
|
+
}
|
|
50
|
+
export function renderReskinSettings() {
|
|
51
|
+
const s = SAMPLE;
|
|
52
|
+
const acct = `<input type="hidden" name="account" value="${rkEscape(s.accountId)}" />`;
|
|
53
|
+
// ---- Profile ----
|
|
54
|
+
const attachmentCards = s.attachments.map((a) => {
|
|
55
|
+
const ext = (a.fileName.split(".").pop() || a.kind).toUpperCase();
|
|
56
|
+
return `
|
|
57
|
+
<div class="rk-item">
|
|
58
|
+
<span class="rk-tile rk-tile-txt rk-tile-sky">${rkEscape(ext)}</span>
|
|
59
|
+
<div class="rk-item-main">
|
|
60
|
+
<div class="rk-item-title">${rkEscape(a.fileName)}</div>
|
|
61
|
+
<div class="rk-item-sub">${rkEscape(a.kind)} · ${rkEscape(a.size)} · added ${rkEscape(a.when)}</div>
|
|
62
|
+
</div>
|
|
63
|
+
<button class="rk-btn rk-btn-ghost rk-btn-sm" type="button">Open</button>
|
|
64
|
+
</div>`;
|
|
65
|
+
}).join("");
|
|
66
|
+
const profile = `
|
|
67
|
+
<div class="rk-card rk-set-panel-card">
|
|
68
|
+
<div class="rk-card-head">
|
|
69
|
+
<span class="rk-eyebrow">Profile</span>
|
|
70
|
+
<h2>Profile, notes & attachments</h2>
|
|
71
|
+
<p class="rk-muted">The product description powers Swipe mode's auto-recut. Attachments are your reusable brand assets.</p>
|
|
72
|
+
</div>
|
|
73
|
+
<form class="rk-stack" method="post" action="/settings/profile">
|
|
74
|
+
${acct}
|
|
75
|
+
<div class="rk-field">
|
|
76
|
+
<label class="rk-label" for="rk-name">Display name</label>
|
|
77
|
+
<input class="rk-input" id="rk-name" type="text" name="display_name" value="${rkEscape(s.name)}" />
|
|
78
|
+
</div>
|
|
79
|
+
<div class="rk-field">
|
|
80
|
+
<label class="rk-label" for="rk-about">Product description</label>
|
|
81
|
+
<textarea class="rk-textarea" id="rk-about" name="about" placeholder="What it is, who it's for, the promise…">${rkEscape(s.about)}</textarea>
|
|
82
|
+
<span class="rk-hint">Swipe mode reads this to auto-recut templates into ads for you.</span>
|
|
83
|
+
</div>
|
|
84
|
+
<div class="rk-field">
|
|
85
|
+
<label class="rk-label">Brand assets</label>
|
|
86
|
+
<div class="rk-set-drop">
|
|
87
|
+
<div><strong>Drop files</strong> or <span class="rk-set-link">browse</span> — logos, fonts, VO, footage.</div>
|
|
88
|
+
</div>
|
|
89
|
+
<div class="rk-list rk-set-attach">${attachmentCards}</div>
|
|
90
|
+
</div>
|
|
91
|
+
<div class="rk-row">
|
|
92
|
+
<button class="rk-btn rk-btn-ink" type="submit">Save changes</button>
|
|
93
|
+
<span class="rk-hint">Signed in as ${rkEscape(s.email)}</span>
|
|
94
|
+
</div>
|
|
95
|
+
</form>
|
|
96
|
+
</div>`;
|
|
97
|
+
// ---- Wallet ----
|
|
98
|
+
const historyRows = s.walletEvents.map((e) => `
|
|
99
|
+
<div class="rk-item">
|
|
100
|
+
<span class="rk-tile rk-tile-sm rk-tile-txt ${e.kind === "credit" ? "rk-tile-green" : "rk-tile-ink"}">${e.kind === "credit" ? "+" : "−"}</span>
|
|
101
|
+
<div class="rk-item-main">
|
|
102
|
+
<div class="rk-item-title">${rkEscape(e.title)}</div>
|
|
103
|
+
<div class="rk-item-sub">${rkEscape(e.sub)} · ${rkEscape(e.when)}</div>
|
|
104
|
+
</div>
|
|
105
|
+
<div class="rk-set-amount ${e.kind === "credit" ? "is-credit" : ""}">${money(e.amountUsd)}</div>
|
|
106
|
+
</div>`).join("");
|
|
107
|
+
const wallet = `
|
|
108
|
+
<div class="rk-stack rk-set-panel">
|
|
109
|
+
<div class="rk-grid rk-grid-2 rk-set-wallet-top">
|
|
110
|
+
<div class="rk-card rk-set-balance">
|
|
111
|
+
<span class="rk-eyebrow">Wallet</span>
|
|
112
|
+
<div class="rk-stat-num rk-set-balance-num">${money(s.wallet.balanceUsd)}</div>
|
|
113
|
+
<p class="rk-muted">Available balance · updated ${rkEscape(s.wallet.updatedAt)}</p>
|
|
114
|
+
<div class="rk-row rk-wrap rk-set-balance-cta">
|
|
115
|
+
<a class="rk-btn rk-btn-gold" href="#">Top up wallet <span class="rk-arrow">→</span></a>
|
|
116
|
+
<span class="rk-pill rk-pill-green">Auto-scales to zero</span>
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
<div class="rk-stack">
|
|
120
|
+
<div class="rk-card rk-card-pad-sm rk-stat">
|
|
121
|
+
<div class="rk-stat-label">Funds added</div>
|
|
122
|
+
<div class="rk-stat-num">${money(s.wallet.totalFundsAddedUsd)}</div>
|
|
123
|
+
</div>
|
|
124
|
+
<div class="rk-card rk-card-pad-sm rk-stat">
|
|
125
|
+
<div class="rk-stat-label">Total usage</div>
|
|
126
|
+
<div class="rk-stat-num">${money(s.wallet.totalChargeUsd)}</div>
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
<div class="rk-card">
|
|
131
|
+
<div class="rk-card-head">
|
|
132
|
+
<span class="rk-eyebrow">Ledger</span>
|
|
133
|
+
<h2>Transparent billing history</h2>
|
|
134
|
+
<p class="rk-muted">Every render and top-up, itemized. You're only charged for compute — BYO AI keys are never billed.</p>
|
|
135
|
+
</div>
|
|
136
|
+
<div class="rk-list">${historyRows}</div>
|
|
137
|
+
<div class="rk-row rk-set-ledger-foot"><button class="rk-btn rk-btn-ghost rk-btn-sm" type="button">Load more</button></div>
|
|
138
|
+
</div>
|
|
139
|
+
</div>`;
|
|
140
|
+
// ---- Channels ----
|
|
141
|
+
const channelCards = s.channels.map((c) => {
|
|
142
|
+
const tint = c.platform === "TikTok" ? "rk-tile-ink" : c.platform === "Instagram" ? "rk-tile-coral" : "rk-tile-sky";
|
|
143
|
+
const initial = rkEscape(c.platform.charAt(0).toUpperCase());
|
|
144
|
+
const statusPill = c.status === "Connected" ? "rk-pill-green" : "rk-pill-gold";
|
|
145
|
+
return `<div class="rk-item">
|
|
146
|
+
<span class="rk-tile rk-tile-txt ${tint}">${initial}</span>
|
|
147
|
+
<div class="rk-item-main">
|
|
148
|
+
<div class="rk-item-title">${rkEscape(c.title)}</div>
|
|
149
|
+
<div class="rk-item-sub">${rkEscape(c.platform)} · ${rkEscape(c.handle)}</div>
|
|
150
|
+
</div>
|
|
151
|
+
<span class="rk-pill ${statusPill}">${rkEscape(c.status)}</span>
|
|
152
|
+
<button class="rk-btn rk-btn-ghost rk-btn-sm" type="button">Manage</button>
|
|
153
|
+
</div>`;
|
|
154
|
+
}).join("");
|
|
155
|
+
const channels = `
|
|
156
|
+
<div class="rk-stack rk-set-panel">
|
|
157
|
+
<div class="rk-card">
|
|
158
|
+
<div class="rk-spread rk-wrap rk-card-head">
|
|
159
|
+
<div>
|
|
160
|
+
<span class="rk-eyebrow">Channels</span>
|
|
161
|
+
<h2>${s.channels.length} connected channels</h2>
|
|
162
|
+
<p class="rk-muted">Where approved cuts get published. Connect via FlockPoster or add an email channel.</p>
|
|
163
|
+
</div>
|
|
164
|
+
<a class="rk-btn rk-btn-ink" href="#">Connect channel <span class="rk-arrow">→</span></a>
|
|
165
|
+
</div>
|
|
166
|
+
<div class="rk-list">${channelCards}</div>
|
|
167
|
+
</div>
|
|
168
|
+
<div class="rk-card">
|
|
169
|
+
<div class="rk-card-head">
|
|
170
|
+
<span class="rk-eyebrow">FlockPoster</span>
|
|
171
|
+
<h3>FlockPoster API key</h3>
|
|
172
|
+
<p class="rk-muted">Paste a FlockPoster key to pull in this workspace's connected social channels.</p>
|
|
173
|
+
</div>
|
|
174
|
+
<form class="rk-stack" method="post" action="/settings/channels/flockposter">
|
|
175
|
+
${acct}
|
|
176
|
+
<div class="rk-field">
|
|
177
|
+
<label class="rk-label" for="rk-fp">API key</label>
|
|
178
|
+
<div class="rk-input-group">
|
|
179
|
+
<input class="rk-input" id="rk-fp" type="password" name="api_key" placeholder="fp_live_…" />
|
|
180
|
+
<button class="rk-btn rk-btn-ghost rk-btn-sm" type="button" data-rk-reveal="rk-fp" aria-label="Show API key">${EYE}</button>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
<div class="rk-row">
|
|
184
|
+
<button class="rk-btn rk-btn-gold" type="submit">Save & test connection</button>
|
|
185
|
+
</div>
|
|
186
|
+
</form>
|
|
187
|
+
</div>
|
|
188
|
+
</div>`;
|
|
189
|
+
// ---- Developer ----
|
|
190
|
+
const keyRows = s.providerKeys.map((k, i) => {
|
|
191
|
+
const id = `rk-pk-${i}`;
|
|
192
|
+
const tint = k.provider === "OpenAI" ? "rk-tile-green" : k.provider === "Gemini" ? "rk-tile-sky" : "rk-tile-violet";
|
|
193
|
+
const initial = rkEscape(k.provider.charAt(0).toUpperCase());
|
|
194
|
+
return `<div class="rk-item">
|
|
195
|
+
<span class="rk-tile rk-tile-txt ${tint}">${initial}</span>
|
|
196
|
+
<div class="rk-item-main">
|
|
197
|
+
<div class="rk-item-title">${rkEscape(k.label)} <span class="rk-pill rk-pill-green">${rkEscape(k.status)}</span></div>
|
|
198
|
+
<div class="rk-item-sub"><span class="rk-mono" id="${id}" data-rk-secret="${rkEscape(k.secret)}">${"•".repeat(18)}</span> · ${rkEscape(k.provider)} · used ${rkEscape(k.lastUsed)}</div>
|
|
199
|
+
</div>
|
|
200
|
+
<button class="rk-btn rk-btn-ghost rk-btn-sm" type="button" data-rk-reveal-text="${id}" aria-label="Show key">${EYE}</button>
|
|
201
|
+
<form method="post" action="/settings/provider-keys/delete" style="display:inline">
|
|
202
|
+
${acct}<input type="hidden" name="id" value="${rkEscape(k.label)}" />
|
|
203
|
+
<button class="rk-btn rk-btn-danger rk-btn-sm" type="submit">Remove</button>
|
|
204
|
+
</form>
|
|
205
|
+
</div>`;
|
|
206
|
+
}).join("");
|
|
207
|
+
const developer = `
|
|
208
|
+
<div class="rk-stack rk-set-panel">
|
|
209
|
+
<div class="rk-card">
|
|
210
|
+
<div class="rk-card-head">
|
|
211
|
+
<span class="rk-eyebrow">Developer</span>
|
|
212
|
+
<h2>Your vidfarm API key</h2>
|
|
213
|
+
<p class="rk-muted">Authenticates the <code>vidfarm</code> CLI and REST calls. Keep it secret.</p>
|
|
214
|
+
</div>
|
|
215
|
+
<div class="rk-field">
|
|
216
|
+
<div class="rk-input-group">
|
|
217
|
+
<input class="rk-input rk-mono" id="rk-vfkey" type="password" value="${rkEscape(s.vidfarmApiKey)}" readonly />
|
|
218
|
+
<button class="rk-btn rk-btn-ghost rk-btn-sm" type="button" data-rk-reveal="rk-vfkey" aria-label="Show key">${EYE}</button>
|
|
219
|
+
<button class="rk-btn rk-btn-ink rk-btn-sm" type="button" data-rk-copy="rk-vfkey">Copy</button>
|
|
220
|
+
</div>
|
|
221
|
+
</div>
|
|
222
|
+
</div>
|
|
223
|
+
<div class="rk-card">
|
|
224
|
+
<div class="rk-spread rk-wrap rk-card-head">
|
|
225
|
+
<div>
|
|
226
|
+
<span class="rk-eyebrow">AI keys</span>
|
|
227
|
+
<h2>Bring your own model keys</h2>
|
|
228
|
+
<p class="rk-muted">Stored per workspace. Used for clip tagging, recaption, and Swipe — never billed by vidfarm.</p>
|
|
229
|
+
</div>
|
|
230
|
+
</div>
|
|
231
|
+
<div class="rk-list rk-set-keys">${keyRows}</div>
|
|
232
|
+
<form class="rk-set-addkey" method="post" action="/settings/provider-keys">
|
|
233
|
+
${acct}
|
|
234
|
+
<div class="rk-grid rk-grid-3 rk-set-addkey-grid">
|
|
235
|
+
<div class="rk-field">
|
|
236
|
+
<label class="rk-label" for="rk-prov">Provider</label>
|
|
237
|
+
<select class="rk-select" id="rk-prov" name="provider">
|
|
238
|
+
<option>OpenAI</option><option>Gemini</option><option>OpenRouter</option><option>Anthropic</option>
|
|
239
|
+
</select>
|
|
240
|
+
</div>
|
|
241
|
+
<div class="rk-field">
|
|
242
|
+
<label class="rk-label" for="rk-prov-label">Label</label>
|
|
243
|
+
<input class="rk-input" id="rk-prov-label" name="label" placeholder="Optional" />
|
|
244
|
+
</div>
|
|
245
|
+
<div class="rk-field">
|
|
246
|
+
<label class="rk-label" for="rk-prov-secret">API key</label>
|
|
247
|
+
<input class="rk-input" id="rk-prov-secret" type="password" name="secret" placeholder="sk-…" />
|
|
248
|
+
</div>
|
|
249
|
+
</div>
|
|
250
|
+
<button class="rk-btn rk-btn-gold" type="submit">Add AI key</button>
|
|
251
|
+
</form>
|
|
252
|
+
</div>
|
|
253
|
+
<div class="rk-card rk-set-skill">
|
|
254
|
+
<div class="rk-item-main">
|
|
255
|
+
<h3>Director skill</h3>
|
|
256
|
+
<p class="rk-muted">The full REST + CLI playbook for driving vidfarm from an agent.</p>
|
|
257
|
+
</div>
|
|
258
|
+
<a class="rk-btn rk-btn-ghost" href="#">Download SKILL.director.md</a>
|
|
259
|
+
</div>
|
|
260
|
+
</div>`;
|
|
261
|
+
const body = `
|
|
262
|
+
<main class="rk-container rk-page">
|
|
263
|
+
<div class="rk-page-head">
|
|
264
|
+
<span class="rk-badge">Account settings</span>
|
|
265
|
+
<h1 class="rk-h1">Settings</h1>
|
|
266
|
+
<p class="rk-sub">Manage your profile, wallet, publishing channels, and developer access.</p>
|
|
267
|
+
</div>
|
|
268
|
+
<div class="rk-shell">
|
|
269
|
+
<nav class="rk-side" aria-label="Settings sections">
|
|
270
|
+
${tabButton("profile", "Profile", true)}
|
|
271
|
+
${tabButton("wallet", "Wallet", false)}
|
|
272
|
+
${tabButton("channels", "Channels", false)}
|
|
273
|
+
${tabButton("developer", "Developer", false)}
|
|
274
|
+
</nav>
|
|
275
|
+
<div class="rk-set-panels">
|
|
276
|
+
<section class="rk-reveal" data-rk-panel="profile">${profile}</section>
|
|
277
|
+
<section class="rk-reveal" data-rk-panel="wallet" hidden>${wallet}</section>
|
|
278
|
+
<section class="rk-reveal" data-rk-panel="channels" hidden>${channels}</section>
|
|
279
|
+
<section class="rk-reveal" data-rk-panel="developer" hidden>${developer}</section>
|
|
280
|
+
</div>
|
|
281
|
+
</div>
|
|
282
|
+
</main>`;
|
|
283
|
+
const pageCss = `
|
|
284
|
+
.rk-tile-txt{font-family:var(--rk-font-display);font-weight:700;font-size:14px;letter-spacing:.01em;line-height:1}
|
|
285
|
+
.rk-tile-txt.rk-tile-sm{font-size:15px}
|
|
286
|
+
.rk-set-panel-card,.rk-set-panel{max-width:760px}
|
|
287
|
+
.rk-set-drop{display:flex;align-items:center;gap:14px;padding:20px;border:1.5px dashed var(--rk-border-strong);border-radius:var(--rk-r-2xl);background:var(--rk-n-50);font-size:14px;color:var(--rk-text-muted)}
|
|
288
|
+
.rk-set-link{color:var(--rk-gold-700);font-weight:600;cursor:pointer}
|
|
289
|
+
.rk-set-attach{margin-top:12px}
|
|
290
|
+
.rk-set-wallet-top{align-items:stretch}
|
|
291
|
+
.rk-set-balance{display:grid;gap:10px;align-content:start}
|
|
292
|
+
.rk-set-balance-num{font-size:var(--rk-text-5xl)}
|
|
293
|
+
.rk-set-balance-cta{margin-top:6px}
|
|
294
|
+
.rk-set-amount{font-family:var(--rk-font-display);font-weight:700;font-size:15px;color:var(--rk-n-600);white-space:nowrap}
|
|
295
|
+
.rk-set-amount.is-credit{color:#16a34a}
|
|
296
|
+
.rk-set-ledger-foot{margin-top:16px;justify-content:center}
|
|
297
|
+
.rk-set-keys{margin-bottom:20px}
|
|
298
|
+
.rk-set-addkey{border-top:1px solid var(--rk-border);padding-top:20px;display:grid;gap:16px}
|
|
299
|
+
.rk-set-addkey-grid{gap:14px}
|
|
300
|
+
.rk-set-skill{display:flex;align-items:center;gap:18px}
|
|
301
|
+
@media(max-width:620px){.rk-set-skill{flex-wrap:wrap}}
|
|
302
|
+
`;
|
|
303
|
+
const script = `
|
|
304
|
+
(function(){
|
|
305
|
+
var root=document;
|
|
306
|
+
// tab switching
|
|
307
|
+
root.querySelectorAll('[data-rk-tab]').forEach(function(btn){
|
|
308
|
+
btn.addEventListener('click',function(){
|
|
309
|
+
var tab=btn.getAttribute('data-rk-tab');
|
|
310
|
+
root.querySelectorAll('[data-rk-tab]').forEach(function(b){b.classList.toggle('is-active',b===btn)});
|
|
311
|
+
root.querySelectorAll('[data-rk-panel]').forEach(function(p){p.hidden=p.getAttribute('data-rk-panel')!==tab});
|
|
312
|
+
if(history.replaceState)history.replaceState(null,'','#'+tab);
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
var hash=(location.hash||'').replace('#','');
|
|
316
|
+
if(hash){var t=root.querySelector('[data-rk-tab="'+hash+'"]');if(t)t.click();}
|
|
317
|
+
// reveal password-style inputs
|
|
318
|
+
root.querySelectorAll('[data-rk-reveal]').forEach(function(btn){
|
|
319
|
+
btn.addEventListener('click',function(){
|
|
320
|
+
var el=root.getElementById(btn.getAttribute('data-rk-reveal'));
|
|
321
|
+
if(!el)return; el.type=el.type==='password'?'text':'password';
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
// reveal masked secret text
|
|
325
|
+
root.querySelectorAll('[data-rk-reveal-text]').forEach(function(btn){
|
|
326
|
+
btn.addEventListener('click',function(){
|
|
327
|
+
var el=root.getElementById(btn.getAttribute('data-rk-reveal-text'));
|
|
328
|
+
if(!el)return; var real=el.getAttribute('data-rk-secret');
|
|
329
|
+
var shown=el.getAttribute('data-rk-shown')==='1';
|
|
330
|
+
el.textContent=shown?'\\u2022'.repeat(18):real; el.setAttribute('data-rk-shown',shown?'0':'1');
|
|
331
|
+
});
|
|
332
|
+
});
|
|
333
|
+
// copy
|
|
334
|
+
root.querySelectorAll('[data-rk-copy]').forEach(function(btn){
|
|
335
|
+
btn.addEventListener('click',function(){
|
|
336
|
+
var el=root.getElementById(btn.getAttribute('data-rk-copy'));
|
|
337
|
+
if(!el||!navigator.clipboard)return;
|
|
338
|
+
navigator.clipboard.writeText(el.value||el.textContent||'').then(function(){
|
|
339
|
+
var t=btn.textContent; btn.textContent='Copied!'; setTimeout(function(){btn.textContent=t},1200);
|
|
340
|
+
});
|
|
341
|
+
});
|
|
342
|
+
});
|
|
343
|
+
})();`;
|
|
344
|
+
return reskinDocument({
|
|
345
|
+
title: "vidfarm reskin — Settings",
|
|
346
|
+
description: "Reskinned vidfarm settings page (profile, wallet, channels, developer).",
|
|
347
|
+
activeSlug: "settings",
|
|
348
|
+
pageCss,
|
|
349
|
+
body,
|
|
350
|
+
script
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
//# sourceMappingURL=settings-page.js.map
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
2
|
+
// /reskin/* shared design system — "farmville-saas-ux" (warm sunny Fillout)
|
|
3
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
4
|
+
// This is the SHARED, ISOLATED stylesheet for the /reskin/* migration surface,
|
|
5
|
+
// where we port old vidfarm pages into the new design system one at a time.
|
|
6
|
+
//
|
|
7
|
+
// CSS isolation contract (do not break it):
|
|
8
|
+
// • Every /reskin page is its own standalone HTML document (see document.ts)
|
|
9
|
+
// with only THIS stylesheet — it never shares a <style> with the live app,
|
|
10
|
+
// so nothing here can conflict with old-page CSS and vice versa.
|
|
11
|
+
// • Belt-and-suspenders: every design token is prefixed `--rk-` and every
|
|
12
|
+
// class is prefixed `rk-`. Even if this CSS were ever inlined next to app
|
|
13
|
+
// CSS, there would be no collision.
|
|
14
|
+
// • Page modules add ONLY page-scoped classes prefixed `rk-<page>-` and lean
|
|
15
|
+
// on the shared primitives below. Never introduce an unprefixed class.
|
|
16
|
+
//
|
|
17
|
+
// The token values are copied from the farmville-saas-ux skill (honey-gold
|
|
18
|
+
// accent over a neutral base, heavy rounded display type, soft cards, glass
|
|
19
|
+
// pill nav, warm-dark footer).
|
|
20
|
+
export const RESKIN_PAGES = [
|
|
21
|
+
{ slug: "settings", label: "Settings", emoji: "⚙️", blurb: "Profile, wallet, channels & developer keys", live: "/settings", done: true },
|
|
22
|
+
{ slug: "library", label: "Library", emoji: "🎬", blurb: "Your projects, renders & mined clips (tabbed)", live: "/library", done: true },
|
|
23
|
+
{ slug: "discover", label: "Discover", emoji: "✨", blurb: "Template feed · swipe · categories", live: "/discover", done: true },
|
|
24
|
+
{ slug: "chat", label: "Brainstorm", emoji: "💬", blurb: "Full AI brainstorm chat", live: "/chat", done: true },
|
|
25
|
+
{ slug: "calendar", label: "Calendar", emoji: "📅", blurb: "Scheduled posts", live: "/calendar", done: true },
|
|
26
|
+
{ slug: "job-runs", label: "Job runs", emoji: "🩺", blurb: "Render & job history", live: "/job-runs", done: true },
|
|
27
|
+
{ slug: "agency", label: "Agency", emoji: "🏢", blurb: "Agency / client workspaces", live: "/agency", done: true },
|
|
28
|
+
{ slug: "pricing", label: "Pricing", emoji: "💳", blurb: "Plans & wallet top-up", live: "/pricing", done: true },
|
|
29
|
+
{ slug: "login", label: "Login", emoji: "🔑", blurb: "Sign in / sign up", live: "/login", done: true },
|
|
30
|
+
{ slug: "help", label: "Help", emoji: "🆘", blurb: "Help & getting started", live: "/help", done: true }
|
|
31
|
+
];
|
|
32
|
+
/** Google Fonts + preconnect for the reskin display/body stack. Put in <head>. */
|
|
33
|
+
export const RESKIN_FONT_LINKS = `<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
34
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
35
|
+
<link href="https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400;500;600;700;800&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">`;
|
|
36
|
+
/** The complete shared stylesheet. Injected once per reskin document. */
|
|
37
|
+
export const RESKIN_CSS = `
|
|
38
|
+
:root{
|
|
39
|
+
--rk-font-display:"Hanken Grotesk","blMelody",ui-sans-serif,system-ui,sans-serif;
|
|
40
|
+
--rk-font-body:"Inter",ui-sans-serif,system-ui,-apple-system,sans-serif;
|
|
41
|
+
--rk-font-mono:ui-monospace,"SFMono-Regular",Menlo,Monaco,Consolas,monospace;
|
|
42
|
+
/* honey gold — the one joy accent */
|
|
43
|
+
--rk-gold-500:#ffc738;--rk-gold-600:#f6c744;--rk-gold-700:#fcb900;--rk-gold-tint:#fff5e4;--rk-gold-tint2:#ffe9cc;
|
|
44
|
+
/* ink + neutral scale */
|
|
45
|
+
--rk-ink:#171717;--rk-n-800:#262626;--rk-n-700:#404040;--rk-n-600:#525252;--rk-n-500:#737373;--rk-n-400:#a3a3a3;
|
|
46
|
+
--rk-n-300:#d4d4d4;--rk-n-200:#ededed;--rk-n-100:#f5f5f5;--rk-n-50:#fbfbfb;--rk-white:#fff;
|
|
47
|
+
/* support pastels */
|
|
48
|
+
--rk-sky:#3f9fe0;--rk-sky-tint:#e2effd;--rk-violet:#9f5bde;--rk-violet-tint:#e4ddfd;
|
|
49
|
+
--rk-green:#22c55e;--rk-green-tint:#dcfce7;--rk-coral:#f97316;--rk-coral-tint:#ffe9cc;
|
|
50
|
+
--rk-red:#ef4444;--rk-red-tint:#fee2e2;
|
|
51
|
+
/* semantic */
|
|
52
|
+
--rk-bg:var(--rk-n-50);--rk-bg-section:var(--rk-n-100);--rk-surface:var(--rk-white);
|
|
53
|
+
--rk-border:var(--rk-n-200);--rk-border-strong:var(--rk-n-300);
|
|
54
|
+
--rk-text:var(--rk-n-700);--rk-text-muted:var(--rk-n-500);--rk-text-faint:var(--rk-n-400);
|
|
55
|
+
/* radius */
|
|
56
|
+
--rk-r-sm:6px;--rk-r-md:8px;--rk-r-lg:10px;--rk-r-xl:12px;--rk-r-2xl:16px;--rk-r-3xl:24px;--rk-r-full:9999px;
|
|
57
|
+
/* shadow — diffuse soft sunlight, never harsh */
|
|
58
|
+
--rk-shadow-xs:0 1px 2px 0 #0000000d;
|
|
59
|
+
--rk-shadow-sm:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;
|
|
60
|
+
--rk-shadow-md:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a;
|
|
61
|
+
--rk-shadow-lg:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;
|
|
62
|
+
--rk-shadow-xl:0 20px 25px -5px #0000001a,0 8px 10px -6px #0000001a;
|
|
63
|
+
--rk-shadow-card:0 1px 2px #0000000d,0 8px 24px -12px #00000014;
|
|
64
|
+
--rk-shadow-nav:0 4px 24px -8px #00000026,0 1px 2px #0000000d;
|
|
65
|
+
--rk-ring-gold:0 0 0 3px var(--rk-gold-600),0 0 14px rgba(246,199,68,.4);
|
|
66
|
+
/* type scale */
|
|
67
|
+
--rk-text-xs:.75rem;--rk-text-sm:.875rem;--rk-text-base:1rem;--rk-text-lg:1.125rem;
|
|
68
|
+
--rk-text-xl:1.25rem;--rk-text-2xl:1.5rem;--rk-text-3xl:1.875rem;--rk-text-4xl:2.25rem;--rk-text-5xl:3rem;
|
|
69
|
+
/* space + motion */
|
|
70
|
+
--rk-container:75rem;--rk-gutter:clamp(1rem,4vw,2rem);--rk-section-y:clamp(3rem,6vw,5rem);
|
|
71
|
+
--rk-glass-blur:16px;--rk-ease:cubic-bezier(.22,1,.36,1);--rk-dur:200ms;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
*,*::before,*::after{box-sizing:border-box}
|
|
75
|
+
.rk-root{margin:0;font-family:var(--rk-font-body);color:var(--rk-text);background:var(--rk-bg);
|
|
76
|
+
-webkit-font-smoothing:antialiased;line-height:1.5;min-height:100vh}
|
|
77
|
+
.rk-root a{text-decoration:none;color:inherit}
|
|
78
|
+
.rk-root h1,.rk-root h2,.rk-root h3,.rk-root h4{font-family:var(--rk-font-display);font-weight:800;
|
|
79
|
+
letter-spacing:-.025em;line-height:1.1;color:var(--rk-ink);margin:0}
|
|
80
|
+
.rk-root p{margin:0}
|
|
81
|
+
.rk-root code{font-family:var(--rk-font-mono);font-size:.9em;background:var(--rk-n-100);
|
|
82
|
+
padding:2px 6px;border-radius:6px;color:var(--rk-n-700)}
|
|
83
|
+
|
|
84
|
+
/* layout */
|
|
85
|
+
.rk-container{width:min(var(--rk-container),100%);margin:0 auto;padding:0 var(--rk-gutter)}
|
|
86
|
+
.rk-container-wide{width:min(85rem,100%);margin:0 auto;padding:0 var(--rk-gutter)}
|
|
87
|
+
.rk-page{padding:40px 0 96px}
|
|
88
|
+
.rk-page-head{display:grid;gap:8px;margin-bottom:32px}
|
|
89
|
+
.rk-h1{font-size:var(--rk-text-4xl);letter-spacing:-.03em}
|
|
90
|
+
.rk-sub{font-size:var(--rk-text-lg);color:var(--rk-text-muted)}
|
|
91
|
+
.rk-stack{display:grid;gap:16px}
|
|
92
|
+
.rk-row{display:flex;align-items:center;gap:12px}
|
|
93
|
+
.rk-spread{display:flex;align-items:center;justify-content:space-between;gap:16px}
|
|
94
|
+
.rk-wrap{flex-wrap:wrap}
|
|
95
|
+
.rk-grid{display:grid;gap:20px}
|
|
96
|
+
.rk-grid-2{grid-template-columns:repeat(2,1fr)}
|
|
97
|
+
.rk-grid-3{grid-template-columns:repeat(3,1fr)}
|
|
98
|
+
.rk-grid-4{grid-template-columns:repeat(4,1fr)}
|
|
99
|
+
@media(max-width:900px){.rk-grid-3,.rk-grid-4{grid-template-columns:repeat(2,1fr)}}
|
|
100
|
+
@media(max-width:620px){.rk-grid-2,.rk-grid-3,.rk-grid-4{grid-template-columns:1fr}}
|
|
101
|
+
.rk-muted{color:var(--rk-text-muted)}.rk-faint{color:var(--rk-text-faint)}
|
|
102
|
+
.rk-mono{font-family:var(--rk-font-mono)}
|
|
103
|
+
|
|
104
|
+
/* app chrome — fixed LEFT sidebar nav + content column */
|
|
105
|
+
.rk-app{min-height:100vh}
|
|
106
|
+
.rk-sidebar{position:fixed;left:0;top:0;bottom:0;width:248px;z-index:50;display:flex;flex-direction:column;gap:4px;
|
|
107
|
+
padding:20px 14px 16px;background:#fff;border-right:1px solid var(--rk-border);overflow-y:auto}
|
|
108
|
+
.rk-content{margin-left:248px;min-height:100vh;background:var(--rk-bg)}
|
|
109
|
+
.rk-sidebar-brand{display:flex;align-items:center;gap:8px;padding:6px 10px 18px;font-family:var(--rk-font-display);
|
|
110
|
+
font-weight:800;font-size:20px;color:var(--rk-ink);letter-spacing:-.02em}
|
|
111
|
+
.rk-sidebar-nav{display:flex;flex-direction:column;gap:3px;flex:1;min-height:0}
|
|
112
|
+
.rk-sidebar-sep{height:1px;background:var(--rk-border);margin:8px}
|
|
113
|
+
.rk-sidebar-item{display:flex;align-items:center;padding:9px 13px;border-radius:var(--rk-r-lg);
|
|
114
|
+
font-size:14px;font-weight:600;color:var(--rk-n-600);white-space:nowrap;
|
|
115
|
+
transition:background var(--rk-dur) var(--rk-ease),color var(--rk-dur) var(--rk-ease)}
|
|
116
|
+
.rk-sidebar-item:hover{background:var(--rk-n-100);color:var(--rk-ink)}
|
|
117
|
+
.rk-sidebar-item.is-active{background:var(--rk-gold-tint);color:var(--rk-ink)}
|
|
118
|
+
.rk-sidebar-foot{display:grid;gap:8px;padding-top:14px;border-top:1px solid var(--rk-border);margin-top:6px}
|
|
119
|
+
.rk-sidebar-foot-link{font-size:12.5px;font-weight:500;color:var(--rk-text-muted);padding:4px 11px;border-radius:var(--rk-r-md)}
|
|
120
|
+
.rk-sidebar-foot-link:hover{color:var(--rk-ink)}
|
|
121
|
+
.rk-sidebar-cta{justify-content:center}
|
|
122
|
+
|
|
123
|
+
/* brand + glass helpers (kept — reused by the sidebar brand + the login page) */
|
|
124
|
+
.rk-glass{background:rgba(255,255,255,.72);backdrop-filter:blur(var(--rk-glass-blur));
|
|
125
|
+
-webkit-backdrop-filter:blur(var(--rk-glass-blur));border:1px solid var(--rk-border);box-shadow:var(--rk-shadow-nav)}
|
|
126
|
+
.rk-brand{display:inline-flex;align-items:center;gap:8px;font-family:var(--rk-font-display);
|
|
127
|
+
font-weight:800;font-size:20px;color:var(--rk-ink);letter-spacing:-.02em;flex:none}
|
|
128
|
+
.rk-brand-mark{width:26px;height:26px;border-radius:8px;background:var(--rk-gold-500);
|
|
129
|
+
display:grid;place-items:center;font-family:var(--rk-font-display);font-weight:800;font-size:15px;
|
|
130
|
+
color:var(--rk-ink);box-shadow:var(--rk-shadow-xs);flex:none}
|
|
131
|
+
.rk-brand-tag{font-family:var(--rk-font-body);font-size:11px;font-weight:600;color:var(--rk-gold-700);
|
|
132
|
+
background:var(--rk-gold-tint2);padding:2px 8px;border-radius:var(--rk-r-full);letter-spacing:.02em}
|
|
133
|
+
|
|
134
|
+
/* narrow: sidebar collapses to a horizontal top strip */
|
|
135
|
+
@media(max-width:900px){
|
|
136
|
+
.rk-sidebar{position:static;width:auto;flex-direction:row;align-items:center;gap:6px;
|
|
137
|
+
padding:10px 14px;border-right:0;border-bottom:1px solid var(--rk-border);overflow-x:auto}
|
|
138
|
+
.rk-sidebar-brand{padding:6px 8px;flex:none}
|
|
139
|
+
.rk-sidebar-nav{flex-direction:row;gap:4px;flex:1}
|
|
140
|
+
.rk-sidebar-sep{display:none}
|
|
141
|
+
.rk-sidebar-item{padding:8px 12px}
|
|
142
|
+
.rk-sidebar-foot{display:none}
|
|
143
|
+
.rk-content{margin-left:0}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/* buttons */
|
|
147
|
+
.rk-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:11px 18px;
|
|
148
|
+
border-radius:var(--rk-r-full);font-family:var(--rk-font-body);font-size:14px;font-weight:600;
|
|
149
|
+
border:1px solid transparent;cursor:pointer;white-space:nowrap;text-align:center;
|
|
150
|
+
transition:transform var(--rk-dur) var(--rk-ease),box-shadow var(--rk-dur) var(--rk-ease),background var(--rk-dur) var(--rk-ease),border-color var(--rk-dur) var(--rk-ease)}
|
|
151
|
+
.rk-btn .rk-arrow{transition:transform var(--rk-dur) var(--rk-ease)}
|
|
152
|
+
.rk-btn:hover .rk-arrow{transform:translateX(3px)}
|
|
153
|
+
.rk-btn-ink{background:var(--rk-ink);color:#fff;box-shadow:var(--rk-shadow-sm)}
|
|
154
|
+
.rk-btn-ink:hover{background:#000;box-shadow:var(--rk-shadow-md);transform:translateY(-1px)}
|
|
155
|
+
.rk-btn-gold{background:var(--rk-gold-500);color:var(--rk-ink);font-weight:700;box-shadow:var(--rk-shadow-sm)}
|
|
156
|
+
.rk-btn-gold:hover{background:var(--rk-gold-700);box-shadow:0 6px 18px -6px rgba(252,185,0,.6);transform:translateY(-1px)}
|
|
157
|
+
.rk-btn-ghost{background:#fff;color:var(--rk-ink);border-color:var(--rk-border);box-shadow:var(--rk-shadow-xs)}
|
|
158
|
+
.rk-btn-ghost:hover{border-color:var(--rk-border-strong);box-shadow:var(--rk-shadow-sm)}
|
|
159
|
+
.rk-btn-danger{background:#fff;color:var(--rk-red);border-color:var(--rk-red-tint)}
|
|
160
|
+
.rk-btn-danger:hover{background:var(--rk-red-tint)}
|
|
161
|
+
.rk-btn-sm{padding:7px 13px;font-size:13px}
|
|
162
|
+
.rk-btn-lg{padding:14px 24px;font-size:15px}
|
|
163
|
+
.rk-btn-block{width:100%}
|
|
164
|
+
|
|
165
|
+
/* badges + pills */
|
|
166
|
+
.rk-badge{display:inline-flex;align-items:center;gap:6px;padding:5px 12px;border-radius:var(--rk-r-full);
|
|
167
|
+
background:#fff;border:1px solid var(--rk-border);box-shadow:var(--rk-shadow-xs);
|
|
168
|
+
font-size:13px;font-weight:500;color:var(--rk-n-700);justify-self:start;width:fit-content}
|
|
169
|
+
.rk-pill{display:inline-flex;align-items:center;gap:6px;padding:4px 11px;border-radius:var(--rk-r-full);
|
|
170
|
+
font-size:12px;font-weight:600;background:var(--rk-n-100);color:var(--rk-n-600)}
|
|
171
|
+
.rk-pill-gold{background:var(--rk-gold-tint2);color:var(--rk-gold-700)}
|
|
172
|
+
.rk-pill-green{background:var(--rk-green-tint);color:#15803d}
|
|
173
|
+
.rk-pill-sky{background:var(--rk-sky-tint);color:#1d6fb8}
|
|
174
|
+
.rk-pill-violet{background:var(--rk-violet-tint);color:#7c3aed}
|
|
175
|
+
.rk-pill-red{background:var(--rk-red-tint);color:#b91c1c}
|
|
176
|
+
|
|
177
|
+
/* cards */
|
|
178
|
+
.rk-card{background:var(--rk-surface);border:1px solid var(--rk-border);border-radius:var(--rk-r-3xl);
|
|
179
|
+
padding:28px;box-shadow:var(--rk-shadow-card)}
|
|
180
|
+
.rk-card-hover{transition:transform var(--rk-dur) var(--rk-ease),box-shadow var(--rk-dur) var(--rk-ease)}
|
|
181
|
+
.rk-card-hover:hover{transform:translateY(-2px);box-shadow:var(--rk-shadow-lg)}
|
|
182
|
+
.rk-card-pad-sm{padding:20px}
|
|
183
|
+
.rk-card h2{font-size:var(--rk-text-2xl);letter-spacing:-.02em}
|
|
184
|
+
.rk-card h3{font-size:var(--rk-text-lg);font-weight:700;font-family:var(--rk-font-display)}
|
|
185
|
+
.rk-card-head{display:grid;gap:6px;margin-bottom:20px}
|
|
186
|
+
.rk-eyebrow{display:inline-flex;align-items:center;gap:6px;font-size:13px;font-weight:600;
|
|
187
|
+
color:var(--rk-gold-700);text-transform:uppercase;letter-spacing:.04em;justify-self:start;width:fit-content}
|
|
188
|
+
|
|
189
|
+
/* icon tiles */
|
|
190
|
+
.rk-tile{width:40px;height:40px;border-radius:var(--rk-r-xl);display:grid;place-items:center;font-size:18px;flex:none}
|
|
191
|
+
.rk-tile-sm{width:32px;height:32px;font-size:15px;border-radius:var(--rk-r-lg)}
|
|
192
|
+
.rk-tile-lg{width:52px;height:52px;font-size:24px}
|
|
193
|
+
.rk-tile-gold{background:var(--rk-gold-tint2);color:var(--rk-gold-700)}
|
|
194
|
+
.rk-tile-sky{background:var(--rk-sky-tint);color:var(--rk-sky)}
|
|
195
|
+
.rk-tile-violet{background:var(--rk-violet-tint);color:var(--rk-violet)}
|
|
196
|
+
.rk-tile-green{background:var(--rk-green-tint);color:#16a34a}
|
|
197
|
+
.rk-tile-coral{background:var(--rk-coral-tint);color:var(--rk-coral)}
|
|
198
|
+
.rk-tile-ink{background:var(--rk-n-100);color:var(--rk-ink)}
|
|
199
|
+
|
|
200
|
+
/* forms */
|
|
201
|
+
.rk-field{display:grid;gap:7px}
|
|
202
|
+
.rk-label{font-size:13px;font-weight:600;color:var(--rk-n-700)}
|
|
203
|
+
.rk-hint{font-size:12px;color:var(--rk-text-muted)}
|
|
204
|
+
.rk-input,.rk-textarea,.rk-select{width:100%;font-family:var(--rk-font-body);font-size:14px;
|
|
205
|
+
color:var(--rk-ink);background:#fff;border:1px solid var(--rk-border-strong);border-radius:var(--rk-r-xl);
|
|
206
|
+
padding:11px 14px;transition:border-color var(--rk-dur) var(--rk-ease),box-shadow var(--rk-dur) var(--rk-ease)}
|
|
207
|
+
.rk-input::placeholder,.rk-textarea::placeholder{color:var(--rk-n-400)}
|
|
208
|
+
.rk-textarea{min-height:110px;resize:vertical;line-height:1.5}
|
|
209
|
+
.rk-select{appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M2 4l4 4 4-4' stroke='%23737373' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 14px center;padding-right:36px}
|
|
210
|
+
.rk-input:focus,.rk-textarea:focus,.rk-select:focus{outline:none;border-color:var(--rk-gold-600);box-shadow:var(--rk-ring-gold)}
|
|
211
|
+
.rk-input-group{display:flex;align-items:stretch;gap:8px}
|
|
212
|
+
.rk-input-group .rk-input{flex:1}
|
|
213
|
+
|
|
214
|
+
/* notice / flash */
|
|
215
|
+
.rk-notice{display:flex;align-items:center;gap:10px;padding:13px 16px;border-radius:var(--rk-r-2xl);
|
|
216
|
+
font-size:14px;font-weight:500;border:1px solid transparent}
|
|
217
|
+
.rk-notice-ok{background:var(--rk-green-tint);color:#15803d;border-color:#bbf7d0}
|
|
218
|
+
.rk-notice-err{background:var(--rk-red-tint);color:#b91c1c;border-color:#fecaca}
|
|
219
|
+
|
|
220
|
+
/* two-column shell with sticky side rail (settings, etc.) */
|
|
221
|
+
.rk-shell{display:grid;grid-template-columns:248px minmax(0,1fr);gap:32px;align-items:start}
|
|
222
|
+
@media(max-width:860px){.rk-shell{grid-template-columns:1fr}}
|
|
223
|
+
.rk-side{position:sticky;top:88px;display:grid;gap:4px;background:#fff;border:1px solid var(--rk-border);
|
|
224
|
+
border-radius:var(--rk-r-2xl);padding:12px;box-shadow:var(--rk-shadow-card)}
|
|
225
|
+
@media(max-width:860px){.rk-side{position:static;grid-auto-flow:column;overflow:auto}}
|
|
226
|
+
.rk-side-item{display:flex;align-items:center;gap:10px;padding:11px 14px;border-radius:var(--rk-r-xl);
|
|
227
|
+
font-size:14px;font-weight:600;color:var(--rk-n-600);cursor:pointer;border:0;background:transparent;
|
|
228
|
+
width:100%;text-align:left;white-space:nowrap;transition:background var(--rk-dur) var(--rk-ease),color var(--rk-dur) var(--rk-ease)}
|
|
229
|
+
.rk-side-item:hover{background:var(--rk-n-100);color:var(--rk-ink)}
|
|
230
|
+
.rk-side-item.is-active{background:var(--rk-gold-tint);color:var(--rk-ink)}
|
|
231
|
+
.rk-side-item.is-active .rk-side-ic{background:var(--rk-gold-500)}
|
|
232
|
+
.rk-side-ic{width:26px;height:26px;border-radius:8px;background:var(--rk-n-100);display:grid;place-items:center;font-size:14px;flex:none}
|
|
233
|
+
|
|
234
|
+
/* simple list rows */
|
|
235
|
+
.rk-list{display:grid;gap:10px;grid-template-columns:minmax(0,1fr)}
|
|
236
|
+
.rk-item{display:flex;align-items:center;gap:14px;padding:14px 16px;background:#fff;min-width:0;
|
|
237
|
+
border:1px solid var(--rk-border);border-radius:var(--rk-r-2xl);box-shadow:var(--rk-shadow-xs)}
|
|
238
|
+
.rk-item-main{flex:1;min-width:0}
|
|
239
|
+
.rk-item-title{font-weight:600;color:var(--rk-ink);font-size:14px}
|
|
240
|
+
.rk-item-sub{font-size:13px;color:var(--rk-text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
241
|
+
|
|
242
|
+
/* stat tiles */
|
|
243
|
+
.rk-stat{display:grid;gap:6px}
|
|
244
|
+
.rk-stat-label{display:flex;align-items:center;gap:8px;font-size:13px;font-weight:600;color:var(--rk-text-muted)}
|
|
245
|
+
.rk-stat-num{font-family:var(--rk-font-display);font-size:var(--rk-text-4xl);font-weight:800;letter-spacing:-.02em;color:var(--rk-ink)}
|
|
246
|
+
|
|
247
|
+
/* footer — warm-dark charcoal */
|
|
248
|
+
.rk-footer{background:var(--rk-ink);color:var(--rk-n-400);padding:56px var(--rk-gutter) 40px;margin-top:64px}
|
|
249
|
+
.rk-footer-inner{width:min(var(--rk-container),100%);margin:0 auto;display:flex;flex-wrap:wrap;gap:24px;align-items:center;justify-content:space-between}
|
|
250
|
+
.rk-footer-brand{font-family:var(--rk-font-display);font-weight:800;font-size:22px;color:var(--rk-gold-500);display:inline-flex;align-items:center;gap:8px}
|
|
251
|
+
.rk-footer a{color:var(--rk-n-300)}.rk-footer a:hover{color:#fff}
|
|
252
|
+
.rk-footer-links{display:flex;gap:8px;flex-wrap:wrap}
|
|
253
|
+
.rk-trust-pill{display:inline-flex;align-items:center;gap:8px;padding:7px 14px;border-radius:var(--rk-r-full);background:#ffffff0d;color:var(--rk-n-400);font-size:13px}
|
|
254
|
+
|
|
255
|
+
/* hero band (sunny sky) — sits flush at the top of the content column */
|
|
256
|
+
.rk-hero-band{position:relative;overflow:hidden;margin-top:0}
|
|
257
|
+
.rk-hero-art{position:absolute;inset:0;z-index:0;background:
|
|
258
|
+
radial-gradient(58% 46% at 78% 20%,rgba(255,241,204,.9),transparent 60%),
|
|
259
|
+
linear-gradient(180deg,#3f9fe0 0%,#6cc0f5 55%,#a9dbfb 100%)}
|
|
260
|
+
.rk-hero{position:relative;z-index:1;text-align:center;padding:119px var(--rk-gutter) 72px}
|
|
261
|
+
|
|
262
|
+
:where(.rk-root a,.rk-root button,.rk-root input,.rk-root textarea,.rk-root select):focus-visible{outline:none;box-shadow:var(--rk-ring-gold)}
|
|
263
|
+
.rk-reveal[hidden]{display:none}
|
|
264
|
+
`;
|
|
265
|
+
//# sourceMappingURL=theme.js.map
|