Diff -- /var/www/vhosts/3dshawn.com/abforge.3dshawn.com/TEMPLATES/abforge_billing.html

O Operator
Diff

/var/www/vhosts/3dshawn.com/abforge.3dshawn.com/TEMPLATES/abforge_billing.html

added on local at 2026-07-01 16:01:47

Added
+442
lines
Removed
-0
lines
Context
0
unchanged
Blobs
from
to 5fe2368f0a29
Restore this content →
Unified diff
Naive LCS-based line diff. Additions in emerald, deletions in rose. Both sides decompressed live from BLOB_STORE.
1<!-- =====================================================================
2 Seller Billing.
3 1. Page head + tutorial button
4 2. Schema-not-ready banner (early-adopter accounts)
5 3. Current subscription card + credit balance card
6 4. Plan picker (upgrade / downgrade)
7 5. Recent invoices table
8 6. Payment method card
9 Data comes from billing.cgi / MODS::ABForge::Billing.
10===================================================================== -->
11
12<style>
13 .bil-grid {
14 display: grid;
15 grid-template-columns: 1fr 1fr;
16 gap: 14px;
17 margin-bottom: 22px;
18 }
19 @media (max-width: 900px) { .bil-grid { grid-template-columns: 1fr; } }
20
21 .bil-pricetag {
22 font-size: 32px; font-weight: 700; color: #fff;
23 font-family: var(--font-mono, monospace);
24 margin-bottom: 4px;
25 }
26 .bil-pricetag .sub { font-size: 14px; color: var(--col-text-3); font-weight: 500; }
27
28 .bil-next {
29 background: var(--col-surface-2);
30 border: 1px solid var(--col-border);
31 border-radius: 10px;
32 padding: 12px 14px;
33 margin-top: 14px;
34 }
35 .bil-next-row { display:flex; justify-content:space-between; font-size:13px; padding:4px 0; }
36 .bil-next-row.bil-next-total { border-top: 1px dashed var(--col-border); margin-top:6px; padding-top:8px; font-weight:700; color:#fff; }
37 .bil-next-row .bil-credit { color: #a78bfa; }
38
39 .bil-creditbox {
40 background: linear-gradient(135deg, rgba(124,58,237,0.16) 0%, rgba(255,122,61,0.10) 100%);
41 border: 1px solid rgba(124,58,237,0.30);
42 border-radius: 12px;
43 padding: 18px 22px;
44 }
45 .bil-creditbox .lbl { font-size: 10px; letter-spacing:1.5px; text-transform:uppercase; color:#c4b5fd; font-weight:700; }
46 .bil-creditbox .val { font-size: 30px; font-weight: 700; color: #fff; font-family: var(--font-mono, monospace); }
47 .bil-creditbox .note { font-size: 12px; color: var(--col-text-2); margin-top: 6px; line-height: 1.5; }
48
49 .bil-ledger { display:flex; flex-direction:column; gap:8px; margin-top:14px; }
50 .bil-ledger-row {
51 display:flex; justify-content:space-between; gap:10px;
52 padding:8px 10px; background: rgba(255,255,255,0.03);
53 border-radius: 8px; font-size: 12px;
54 }
55 .bil-ledger-row .amt { font-family: var(--font-mono, monospace); font-weight: 700; flex-shrink:0; }
56 .bil-ledger-row .amt.pos { color: #4ade80; }
57 .bil-ledger-row .amt.neg { color: #fbbf24; }
58
59 .bil-plans {
60 display: grid;
61 grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
62 gap: 14px;
63 margin-bottom: 24px;
64 }
65 .bil-plan-card {
66 background: var(--col-surface-1);
67 border: 1px solid var(--col-border);
68 border-radius: 14px;
69 padding: 18px;
70 position: relative;
71 transition: border-color 0.15s, transform 0.15s, box-shadow 0.15s;
72 /* Flex column so the action footer (form / "current" note) hugs the
73 bottom edge regardless of how many feature bullets the card has.
74 Without this the PRO card's extra bullet pushes its button below
75 the others. */
76 display: flex;
77 flex-direction: column;
78 }
79 .bil-plan-card.is-current {
80 border-color: var(--col-accent);
81 box-shadow: 0 0 0 2px var(--col-accent) inset, 0 8px 32px rgba(99,102,241,0.18);
82 background: linear-gradient(180deg, rgba(99,102,241,0.10), rgba(99,102,241,0.02) 60%);
83 }
84 .bil-plan-card:hover { transform: translateY(-2px); }
85 .bil-plan-card .badge {
86 position: absolute; top: 14px; right: 14px;
87 font-size: 9px; font-weight: 700;
88 letter-spacing: 1.5px; text-transform: uppercase;
89 color: var(--col-accent-bright);
90 background: rgba(99,102,241,0.18);
91 border: 1px solid rgba(99,102,241,0.45);
92 padding: 3px 8px; border-radius: 999px;
93 }
94 .bil-plan-card .tier { font-size: 12px; font-weight: 700; letter-spacing:1.5px; text-transform:uppercase; color: var(--col-text-3); }
95 .bil-plan-card.is-current .tier { color: var(--col-accent-bright); }
96 .bil-plan-card .price { font-size: 28px; font-weight: 700; color: #fff; font-family: var(--font-mono, monospace); margin-top: 8px; }
97 .bil-plan-card .price .sub { font-size: 13px; color: var(--col-text-3); font-weight: 500; }
98 .bil-plan-card .annual { font-size: 11px; color: var(--col-text-3); margin-top: 2px; }
99 .bil-plan-card ul { list-style: none; padding: 0; margin: 14px 0; display: flex; flex-direction: column; gap: 6px; }
100 .bil-plan-card li { font-size: 12px; color: var(--col-text-2); display: flex; gap: 6px; align-items: flex-start; }
101 .bil-plan-card li.in { color: var(--col-text); }
102 .bil-plan-card li.out { color: var(--col-text-3); text-decoration: line-through; }
103 .bil-plan-card .check { color: #4ade80; flex-shrink: 0; }
104 .bil-plan-card .cross { color: var(--col-text-3); flex-shrink: 0; }
105 /* margin-top:auto pushes the action footer to the bottom of the
106 flex-column so every card's button sits at the same Y. */
107 .bil-plan-card form,
108 .bil-plan-card .bil-plan-current-note {
109 display: flex; flex-direction: column; gap: 6px;
110 margin-top: auto;
111 }
112
113 .bil-itable { width: 100%; border-collapse: separate; border-spacing: 0;
114 background: var(--col-surface-1);
115 border: 1px solid var(--col-border);
116 border-radius: 12px; overflow: hidden; }
117 .bil-itable thead th {
118 background: var(--col-surface-2); padding: 11px 14px;
119 text-align: left; font-size: 10px; letter-spacing: 1.5px;
120 text-transform: uppercase; color: var(--col-text-3); font-weight: 700;
121 border-bottom: 1px solid var(--col-border);
122 }
123 .bil-itable tbody td { padding: 12px 14px; border-bottom: 1px solid var(--col-border); font-size: 13px; color: var(--col-text-2); vertical-align: middle; }
124 .bil-itable tbody tr:last-child td { border-bottom: none; }
125 .bil-itable .num { text-align: right; font-family: var(--font-mono, monospace); }
126 .bil-itable .num.credit { color: #a78bfa; }
127 .bil-itable .num.cash { color: #4ade80; }
128 .bil-itable .pill { font-size: 9px; font-weight: 700; padding: 3px 8px; border-radius: 6px; letter-spacing: 1px; text-transform: uppercase; }
129 .bil-itable .pill.paid { background: rgba(34,197,94,0.18); color: #4ade80; }
130 .bil-itable .pill.open { background: rgba(245,158,11,0.18); color: #fbbf24; }
131 .bil-itable .pill.failed { background: rgba(239,68,68,0.20); color: #f87171; }
132 .bil-itable .pill.refunded { background: rgba(124,58,237,0.18); color: #a78bfa; }
133 .bil-itable .pill.void { background: rgba(100,116,139,0.20); color: #94a3b8; }
134</style>
135
136<div class="page-head">
137 <div>
138 <span class="page-eyebrow"><span class="dot"></span> Account &middot; Billing</span>
139 <h1 class="page-title">Billing &amp; credits</h1>
140 <p class="page-subtitle">Your subscription, credit balance, invoice history, and payment method. Refunds are issued as account credit and applied automatically to your next invoice before any card is charged.</p>
141 </div>
142 <div class="page-actions">
143 [if:$not_tutorial_mode]<a href="/billing.cgi?tutorial=1" class="btn btn-secondary"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>Sample Data View</a>[/if]
144 [if:$tutorial_mode]<a href="/billing.cgi" class="btn btn-secondary"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>Exit sample view</a>[/if]
145 </div>
146</div>
147
148[if:$has_resume_plan]
149<div class="banner mb-3" style="display:flex;gap:12px;align-items:center;padding:14px 16px;border-radius:10px;background:linear-gradient(135deg, rgba(99,102,241,0.12), rgba(139,92,246,0.08));border:1px solid rgba(99,102,241,0.4)">
150 <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="#a5b4fc" stroke-width="2" style="flex:0 0 auto"><polyline points="20 6 9 17 4 12"/></svg>
151 <div style="flex:1">
152 <div class="fw-700" style="color:#fff;font-size:14px">Card saved. Ready to finish your upgrade?</div>
153 <div class="text-sm" style="color:var(--col-text-2);margin-top:2px">Click below to switch to <strong>$resume_plan_label</strong> and charge <strong>$resume_charge_str</strong> now.</div>
154 </div>
155 <form method="POST" action="/billing_action.cgi" style="margin:0">
156 <input type="hidden" name="act" value="change_plan">
157 <input type="hidden" name="plan_id" value="$resume_plan_id">
158 <button type="submit" class="btn btn-primary btn-sm">Complete upgrade</button>
159 </form>
160</div>
161[/if]
162
163[if:$has_plan_flash]
164<div class="banner [if:$plan_flash_is_ok]success[/if][if:$plan_flash_is_err]error[/if] mb-3" style="display:flex;gap:10px;align-items:flex-start;padding:12px 14px;border-radius:10px">
165 <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" style="flex:0 0 auto;margin-top:1px">
166 [if:$plan_flash_is_ok]<polyline points="20 6 9 17 4 12"/>[/if]
167 [if:$plan_flash_is_err]<circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/>[/if]
168 </svg>
169 <div class="text-sm fw-600">$plan_flash_msg</div>
170</div>
171[/if]
172
173[if:$tutorial_mode]
174<div class="tutorial-banner">
175 <div class="tutorial-banner-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></div>
176 <div class="tutorial-banner-body">
177 <div class="tutorial-banner-title">Tutorial &middot; Sample data only</div>
178 <div class="tutorial-banner-text">Every panel below is filled with example data &mdash; an imaginary Pro-tier account with <strong>\$12.00 of credit</strong> on file, four past invoices, and a credit-applied next charge. Use this to see how billing reads when you have history.</div>
179 </div>
180 <a href="/billing.cgi" class="btn btn-secondary btn-sm">Exit sample view</a>
181</div>
182
183<div class="tutorial-intro">
184 <div class="tutorial-intro-eyebrow">A walkthrough of Account &middot; Billing</div>
185 <h2 class="tutorial-intro-title">Here is how billing and credits work on ABForge.</h2>
186 <p class="tutorial-intro-text">Every subscription charge runs through one simple rule: <strong>your credit balance is applied before your card is charged</strong>. If you have \$12 of credit and your monthly plan is \$29, the next invoice charges \$17 in cash and consumes the \$12 of credit. If your credit covers the whole invoice, your card is never touched that month. The <em>Credit balance</em> panel on the right shows your running balance and every grant or consumption that affected it.</p>
187 <p class="tutorial-intro-text">When you ask for a refund, ABForge issues it as <strong>account credit</strong> rather than returning money to your card. The credit goes straight into your balance and is auto-applied to your next bill. This keeps the math clean for your business taxes (no card refunds to reconcile) and gives you faster relief than a card refund (which takes 5-10 business days to settle). The recent-invoices table below uses the <em>Refunded as credit</em> status to call out which invoices triggered credit grants.</p>
188 <p class="tutorial-intro-text tutorial-intro-foot">When you are ready to see your live billing, click <a href="/billing.cgi" class="text-brand fw-700">Exit sample view</a>.</p>
189</div>
190[/if]
191
192[if:$schema_missing]
193<div class="an-banner" style="background:rgba(245,158,11,0.10);border-color:rgba(245,158,11,0.30)">
194 <strong>Billing schema not yet installed.</strong> Run the latest <code>db_schema.sql</code> against your database to bring the billing tables online; once installed, this page populates with your real subscription, credit balance, and invoices.
195</div>
196[/if]
197
198[if:$schema_ready]
199<!-- Current subscription + credit balance -->
200<div class="bil-grid">
201 <div class="module">
202 <div class="module-head">
203 <div class="left">
204 <div class="module-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="5" width="20" height="14" rx="2"/><line x1="2" y1="10" x2="22" y2="10"/></svg></div>
205 <div>
206 <div class="module-title">Current plan</div>
207 <div class="module-sub">$sub_plan_label &middot; $sub_cadence_label cadence</div>
208 </div>
209 </div>
210 <span class="pill brand">$sub_status_label</span>
211 </div>
212 <div class="module-body">
213 <div class="bil-pricetag">$sub_price <span class="sub">/ $sub_cadence_label</span></div>
214 <div class="text-xs text-dim">Next charge: <strong style="color:#fff">$sub_next_charge</strong></div>
215
216 [if:$sub_is_canceling]
217 <div class="text-xs" style="color:#fbbf24;margin-top:8px">Cancels at period end &mdash; you will not be charged again.</div>
218 [/if]
219 [if:$sub_is_past_due]
220 <div class="text-xs" style="color:#f87171;margin-top:8px">Past due &mdash; we will retry the card automatically. Update your payment method below if the issue persists.</div>
221 [/if]
222 [if:$sub_is_trialing]
223 <div class="text-xs" style="color:#a78bfa;margin-top:8px">Free trial in progress. The first paid invoice generates when your trial ends.</div>
224 [/if]
225
226 <div class="bil-next">
227 <div class="text-xs text-dim" style="letter-spacing:1.5px;text-transform:uppercase;margin-bottom:6px">Next invoice preview</div>
228 <div class="bil-next-row"><span>Plan charge</span><span>$next_charge_display</span></div>
229 [if:$has_next_credit_applied]
230 <div class="bil-next-row"><span class="bil-credit">Credit applied</span><span class="bil-credit">-$next_credit_display</span></div>
231 [/if]
232 <div class="bil-next-row bil-next-total"><span>Cash due to card</span><span>$next_cash_display</span></div>
233 [if:$next_cash_due_zero]
234 <div class="text-xs" style="color:#4ade80;margin-top:6px">Your credit covers the full charge &mdash; no card will be billed this period.</div>
235 [/if]
236 </div>
237 </div>
238 </div>
239
240 <div class="module">
241 <div class="module-head">
242 <div class="left">
243 <div class="module-icon" style="background:rgba(124,58,237,0.18);color:var(--col-violet-bright)"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 1v22M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/></svg></div>
244 <div>
245 <div class="module-title">Credit balance</div>
246 <div class="module-sub">Applied automatically to your next invoice</div>
247 </div>
248 </div>
249 </div>
250 <div class="module-body">
251 <div class="bil-creditbox">
252 <div class="lbl">Available credit</div>
253 <div class="val">$credit_balance_display</div>
254 [if:$has_credit_balance]
255 <div class="note">This credit is applied to your <strong>next invoice</strong> before your card is charged. If your credit covers the bill in full, your card is never touched that period.</div>
256 [/if]
257 [if:!$has_credit_balance]
258 <div class="note">You have no account credit right now. If you ever request a refund it will be added here automatically.</div>
259 [/if]
260 </div>
261
262 [if:$has_credit_history]
263 <div class="text-xs text-dim mt-3" style="letter-spacing:1.5px;text-transform:uppercase">Recent activity</div>
264 <div class="bil-ledger">
265 [loop:@credit_rows]
266 <div class="bil-ledger-row">
267 <div>
268 <div style="color:var(--col-text)">$loop1.reason_label</div>
269 [if:$loop1.has_note]<div class="text-xs text-dim">$loop1.note</div>[/if]
270 <div class="text-xs text-dim">$loop1.created_at</div>
271 </div>
272 <div class="amt [if:$loop1.is_positive]pos[/if][if:$loop1.is_negative]neg[/if]">$loop1.amount_display</div>
273 </div>
274 [/loop]
275 </div>
276 [/if]
277 </div>
278 </div>
279</div>
280
281<!-- Promo code -->
282<h2 style="font-size:18px;margin:18px 0 14px;color:var(--col-text)">Have a promo code?</h2>
283<div class="module" style="margin-bottom:18px">
284 <div class="module-body">
285 [if:$has_active_promo]
286 <!-- Live offer banner. Driven by Promotions.pm::active_plan_promo
287 on the seller's billing page so the deal is impossible to miss. -->
288 <div style="display:flex;align-items:center;gap:12px;padding:10px 14px;margin-bottom:14px;border-radius:10px;background:linear-gradient(135deg,rgba(34,197,94,0.10),rgba(124,58,237,0.10));border:1px solid rgba(34,197,94,0.35);flex-wrap:wrap">
289 <span style="display:inline-flex;align-items:center;gap:6px;padding:3px 10px;border-radius:999px;background:rgba(34,197,94,0.18);color:#86efac;font-size:10.5px;font-weight:800;letter-spacing:1.5px;text-transform:uppercase">Limited-time</span>
290 <div style="color:#fff;font-size:13px;font-weight:600">$active_promo_label with code <code style="background:rgba(255,255,255,0.10);padding:2px 7px;border-radius:5px;font-family:var(--font-mono,monospace);font-weight:700">$active_promo_code</code></div>
291 </div>
292 [/if]
293 [if:$has_promo_flash]
294 <div class="banner $promo_flash_kind" style="margin-bottom:14px">
295 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
296 <div class="text-xs">$promo_flash_msg</div>
297 </div>
298 [/if]
299 <form method="POST" action="/billing_action.cgi" style="display:flex;gap:10px;align-items:center;flex-wrap:wrap">
300 <input type="hidden" name="act" value="apply_promo_code">
301 <input class="input" type="text" name="promo_code" value="$active_promo_code" placeholder="ENTER CODE" autocomplete="off" maxlength="64" style="text-transform:uppercase;max-width:260px;flex:1">
302 <button type="submit" class="btn btn-primary">Apply code</button>
303 </form>
304 <div class="text-xs text-dim" style="margin-top:8px;line-height:1.5">
305 Codes apply to your next invoice automatically by adding promotional credit equal to the discount. The discount is calculated against your current plan's price &mdash; if you are on Free, upgrade first to benefit.
306 </div>
307 </div>
308</div>
309
310<!-- Pending-change banner: surfaces a scheduled downgrade (the seller
311 chose a lower tier; we wait until the current paid cycle ends
312 before flipping plan_id). Always above the plan picker so the
313 state is obvious before they try to pick another plan. -->
314[if:$has_pending_change]
315<div style="display:flex;align-items:flex-start;gap:12px;padding:12px 14px;margin:18px 0 0;border-radius:10px;background:rgba(251,191,36,0.12);border:1px solid rgba(251,191,36,0.35)">
316 <svg viewBox="0 0 24 24" fill="none" stroke="#fbbf24" stroke-width="2" style="width:18px;height:18px;flex:0 0 auto;margin-top:1px"><circle cx="12" cy="12" r="10"/><polyline points="12,6 12,12 16,14"/></svg>
317 <div style="font-size:13px;line-height:1.55;color:#fde68a">
318 Scheduled to switch to <strong style="color:#fff">$pending_plan_label</strong> ($pending_cadence_label) on <strong style="color:#fff">$pending_change_at</strong>. You will keep your current plan until then since you have already paid for this cycle.
319 <form method="POST" action="/billing_action.cgi" style="display:inline-block;margin-left:6px">
320 <input type="hidden" name="act" value="clear_pending_change">
321 <button type="submit" class="btn btn-secondary btn-sm" style="padding:3px 10px">Keep current plan</button>
322 </form>
323 </div>
324</div>
325[/if]
326
327<!-- Plan picker -->
328[if:$has_plans]
329<h2 id="change-plan" style="font-size:18px;margin:18px 0 14px;color:var(--col-text)">Change plan</h2>
330<div class="bil-plans">
331 [loop:@plan_cards]
332 <div class="bil-plan-card[if:$loop1.is_current] is-current[/if]">
333 [if:$loop1.is_current]<div class="badge">Current</div>[/if]
334 <div class="tier">$loop1.tier_label</div>
335 <div class="price">$loop1.price_monthly <span class="sub">/ mo</span></div>
336 <div class="annual">or $loop1.price_annual / year</div>
337 <ul>
338 [loop:@loop1.features]
339 <li class="[if:$loop2.included]in[/if][if:!$loop2.included]out[/if]">
340 [if:$loop2.included]<span class="check">&#10003;</span>[/if]
341 [if:!$loop2.included]<span class="cross">&#10005;</span>[/if]
342 <span>$loop2.name</span>
343 </li>
344 [/loop]
345 </ul>
346 [if:!$loop1.is_current]
347 [ptag:manage_billing]
348 <form method="POST" action="/billing_action.cgi"
349 data-confirm-title="$loop1.confirm_title"
350 data-confirm-message="$loop1.confirm_message"
351 data-confirm-label="$loop1.confirm_label"
352 data-confirm-cancel="Keep current plan"
353 data-confirm-style="$loop1.confirm_style">
354 <input type="hidden" name="act" value="change_plan">
355 <input type="hidden" name="plan_id" value="$loop1.plan_id_monthly">
356 <button class="btn btn-primary btn-sm" type="submit">Switch to $loop1.tier_label</button>
357 </form>
358 [/ptag:manage_billing]
359 [/if]
360 [if:$loop1.is_current]
361 <div class="bil-plan-current-note">
362 <div class="btn btn-secondary btn-sm" style="cursor:default;text-align:center;background:rgba(99,102,241,0.14);border:1px solid rgba(99,102,241,0.45);color:var(--col-accent-bright);font-weight:700">Your current plan</div>
363 </div>
364 [/if]
365 </div>
366 [/loop]
367</div>
368[/if]
369
370<!-- Recent invoices -->
371<h2 style="font-size:18px;margin:18px 0 14px;color:var(--col-text)">Invoice history</h2>
372[if:$has_invoices]
373<table class="bil-itable">
374 <thead>
375 <tr>
376 <th>Invoice</th>
377 <th>Period</th>
378 <th class="num">Amount due</th>
379 <th class="num">Credit applied</th>
380 <th class="num">Cash paid</th>
381 <th>Status</th>
382 </tr>
383 </thead>
384 <tbody>
385 [loop:@invoices]
386 <tr>
387 <td><strong style="color:var(--col-text)">$loop1.invoice_number</strong>
388 [if:$loop1.has_failure]<div class="text-xs" style="color:#f87171">$loop1.failure_reason</div>[/if]
389 </td>
390 <td>$loop1.period_label</td>
391 <td class="num">$loop1.amount_due_display</td>
392 <td class="num credit">$loop1.credit_applied_display</td>
393 <td class="num cash">$loop1.cash_paid_display</td>
394 <td>
395 [if:$loop1.is_paid]<span class="pill paid">Paid</span>[/if]
396 [if:$loop1.is_open]<span class="pill open">Open</span>[/if]
397 [if:$loop1.is_failed]<span class="pill failed">Failed</span>[/if]
398 [if:$loop1.is_refunded]<span class="pill refunded">Refunded as credit</span>[/if]
399 [if:$loop1.is_void]<span class="pill void">Void</span>[/if]
400 </td>
401 </tr>
402 [/loop]
403 </tbody>
404</table>
405[/if]
406[if:!$has_invoices]
407<div style="text-align:center;padding:36px 18px;background:var(--col-surface-1);border:1px solid var(--col-border);border-radius:12px">
408 <div class="text-sm fw-600" style="color:#fff;margin-bottom:6px">No invoices yet</div>
409 <div class="text-xs text-dim">Your first invoice issues on your billing anchor date once you are on a paid plan.</div>
410</div>
411[/if]
412
413<!-- Payment method -->
414<h2 style="font-size:18px;margin:24px 0 14px;color:var(--col-text)">Payment method</h2>
415<div class="module">
416 <div class="module-body" style="display:flex;align-items:center;justify-content:space-between;gap:14px">
417 [if:$has_pm]
418 <div style="display:flex;align-items:center;gap:14px">
419 <div style="width:48px;height:32px;border-radius:6px;background:linear-gradient(135deg,#1e293b,#334155);display:grid;place-items:center;font-size:11px;font-weight:700;color:#fff">CARD</div>
420 <div>
421 <div class="text-sm fw-600" style="color:var(--col-text)">$pm_brand_label &middot;&middot;&middot;&middot; $pm_last4</div>
422 <div class="text-xs text-dim">Expires $pm_exp</div>
423 </div>
424 </div>
425 [ptag:manage_billing]
426 <a href="/billing_payment.cgi" class="btn btn-secondary btn-sm">Manage cards</a>
427 [/ptag:manage_billing]
428 [/if]
429 [if:!$has_pm]
430 <div>
431 <div class="text-sm fw-600" style="color:var(--col-text);margin-bottom:4px">No payment method on file</div>
432 <div class="text-xs text-dim">Required for paid plans. Free plan does not need a card.</div>
433 </div>
434 [ptag:manage_billing]
435 <a href="/billing_payment.cgi" class="btn btn-primary btn-sm">Add a card</a>
436 [/ptag:manage_billing]
437 [/if]
438 </div>
439</div>
440[/if]
441
442<div class="adm-foot-spacer" data-end="billing">&nbsp;</div>