fix: redesign /billing layout with design tokens + grid

The page was using the .two-column class (designed for the product
page mobile stack) which left the Stripe Element floating to the
right with massive whitespace and orphaned Review Order / Checkout
buttons disconnected from the content above. Inline styles all over
the PayPal section meant no token consumption.

Rebuild:
- New .billing-page wrapper, max-width 1000px, centered, CSS Grid.
- Active Card + Add Card now sit in a .settings-form-grid (1 col
  mobile, 2 cols desktop) so they align as equal-width siblings.
  Heading copy adapts: "Add a Card" when no card on file, "Add
  Another Card" when there is one.
- PayPal section moved to its own full-width well below; inline
  styles replaced with tokenized .billing-paypal-card,
  .billing-paypal-header, .billing-meta classes. Grid only.
- Review Order + Checkout buttons land in a .billing-actions well
  centered as a 2-col grid; Checkout is the green primary CTA.
  Collapses to a single stretched column on mobile.

No design system tokens are hard-coded — every color, gap, radius,
and font size pulls from tokens.css. CSS Grid only, no flexbox.
This commit is contained in:
russell@unturf.com 2026-05-13 11:06:33 -04:00
parent 7b7d643b15
commit 10074a1d20
No known key found for this signature in database
2 changed files with 122 additions and 63 deletions

View file

@ -3231,6 +3231,78 @@ img.crypto-button-icon {
color: var(--color-green-dark, #8ab34e);
}
/* ====================================================================
/billing card + PayPal management page.
==================================================================== */
.billing-page {
display: grid;
gap: var(--space-5, 20px);
max-width: 1000px;
margin-left: auto;
margin-right: auto;
padding: 0 var(--space-3, 12px);
}
.billing-cards-grid {
align-items: start;
}
.billing-meta {
color: var(--text-secondary, #666);
margin: 0 0 var(--space-3, 12px) 0;
}
.billing-divider {
border: 0;
border-top: 1px solid var(--border-light, #eeeeee);
margin: var(--space-5, 20px) 0;
}
.billing-paypal-well {
/* Full-width below the cards grid. */
}
.billing-paypal-card {
display: grid;
gap: var(--space-3, 12px);
background: var(--alert-info-bg, #dce8ff);
border-left: 4px solid #0070ba;
border-radius: var(--radius-md, 8px);
padding: var(--space-4, 16px);
}
.billing-paypal-header {
display: grid;
grid-template-columns: auto 1fr;
align-items: center;
gap: var(--space-2, 8px);
color: #0070ba;
}
.billing-paypal-logo {
display: block;
}
.billing-inline-form {
margin: 0;
}
.billing-actions {
display: grid;
grid-template-columns: auto auto;
justify-content: center;
gap: var(--space-4, 16px);
margin: 0;
}
@media (max-width: 640px) {
.billing-actions {
grid-template-columns: 1fr;
justify-content: stretch;
}
}
/* Phase 1: Static inline style replacements */
.no-bottom-margin {
margin-bottom: 0px;

View file

@ -3,79 +3,66 @@
{% block content -%}
<section class="two-column">
<section class="billing-page">
<section class="existing-cards well">
<div class="settings-form-grid billing-cards-grid">
<h3>Active Card</h3>
<section class="well">
<h3 class="type-title">Active Card</h3>
The active card will be charged during checkout.
{% if active_card %}
<p class="billing-meta">The active card will be charged during checkout.</p>
{{ stripe.display_card(active_card, actions=False) }}
{% else %}
<p class="billing-meta">No card on file yet. Add one on the right to enable credit-card checkout.</p>
{% endif %}
<br/>
{% if active_card %}
{{ stripe.display_card(active_card, actions=False) }}
{% endif %}
{% if cards|length >= 1 %}
<hr class="billing-divider" />
<h3 class="type-title">Saved Cards</h3>
{% for card in cards %}
{{ stripe.display_card(card) }}
{% endfor %}
{% endif %}
</section>
{% if cards |length >= 1 %}
<section class="well">
<h3 class="type-title">{% if active_card %}Add Another Card{% else %}Add a Card{% endif %}</h3>
{{ stripe.new_card() }}
</section>
<hr>
<br>
</div>
<h3>Saved Cards</h3>
{% for card in cards %}
{{ stripe.display_card(card) }}
<br/>
{% endfor %}
<br/>
{% endif %}
{% if paypal_enabled and paypal_user_shop %}
<section class="well billing-paypal-well">
<h3 class="type-title">PayPal Payment Method</h3>
</section>
<section class="new-card well">
{{ stripe.new_card() }}
</section>
</section>
{# PayPal Saved Payment Method Section #}
{% if paypal_enabled and paypal_user_shop %}
<section class="well" style="margin-top: 20px;">
<h3>PayPal Payment Method</h3>
{% if paypal_user_shop.has_saved_payment_method %}
<div style="padding: 15px; background-color: #f0f7ff; border-left: 4px solid #0070ba; border-radius: 4px; margin-top: 10px;">
<div style="display: flex; align-items: center; gap: 10px; margin-bottom: 8px;">
<svg width="24" height="24" viewBox="0 0 24 24" fill="#0070ba">
<path d="M20.067 8.478c.492.88.556 2.014.3 3.327-.74 3.806-3.276 5.12-6.514 5.12h-.5a.805.805 0 00-.794.68l-.04.22-.63 3.993-.032.17a.804.804 0 01-.794.679H7.72a.483.483 0 01-.477-.558L9.01 8.975a.964.964 0 01.951-.814h2.053c3.893 0 6.535 1.62 7.055 6.317z"/>
<path d="M10.964 8.975a.964.964 0 00-.95.814L8.247 21.891a.483.483 0 00.476.558h3.344c.336 0 .622-.243.678-.574l.028-.15.63-3.994.04-.218a.805.805 0 01.795-.68h.5c3.238 0 5.774-1.314 6.514-5.12.256-1.313.192-2.447-.3-3.327a3.918 3.918 0 00-1.172-1.241c-.67-.437-1.53-.695-2.527-.827-.27-.036-.549-.063-.837-.083h-.18z" opacity=".7"/>
</svg>
<span style="font-weight: 500; font-size: 16px;">PayPal Account Connected</span>
{% if paypal_user_shop.has_saved_payment_method %}
<div class="billing-paypal-card">
<div class="billing-paypal-header">
<svg class="billing-paypal-logo" width="24" height="24" viewBox="0 0 24 24" aria-hidden="true">
<path d="M20.067 8.478c.492.88.556 2.014.3 3.327-.74 3.806-3.276 5.12-6.514 5.12h-.5a.805.805 0 00-.794.68l-.04.22-.63 3.993-.032.17a.804.804 0 01-.794.679H7.72a.483.483 0 01-.477-.558L9.01 8.975a.964.964 0 01.951-.814h2.053c3.893 0 6.535 1.62 7.055 6.317z" fill="#0070ba"/>
<path d="M10.964 8.975a.964.964 0 00-.95.814L8.247 21.891a.483.483 0 00.476.558h3.344c.336 0 .622-.243.678-.574l.028-.15.63-3.994.04-.218a.805.805 0 01.795-.68h.5c3.238 0 5.774-1.314 6.514-5.12.256-1.313.192-2.447-.3-3.327a3.918 3.918 0 00-1.172-1.241c-.67-.437-1.53-.695-2.527-.827-.27-.036-.549-.063-.837-.083h-.18z" fill="#0070ba" opacity=".7"/>
</svg>
<strong>PayPal Account Connected</strong>
</div>
<p class="billing-meta">Your PayPal account is saved for quick checkout. Click the PayPal button at checkout to complete your purchase.</p>
<form method="POST" action="/billing/disconnect-paypal" class="billing-inline-form">
<input type="hidden" name="csrf_token" value="{{ request.session.get_csrf_token() }}" />
<button type="submit" class="mps-button mps-button-small">Disconnect PayPal</button>
</form>
</div>
<p style="margin: 0 0 12px 0; color: #666; font-size: 14px;">
Your PayPal account is saved for quick checkout. Click the PayPal button at checkout to complete your purchase.
</p>
<form method="POST" action="/billing/disconnect-paypal" style="margin: 0;">
<input type="hidden" name="csrf_token" value="{{ request.session.get_csrf_token() }}">
<button type="submit" style="padding: 8px 16px; background-color: #fff; border: 1px solid #ccc; border-radius: 4px; cursor: pointer; font-size: 14px; color: #333;">
Disconnect PayPal
</button>
</form>
</div>
{% else %}
<p style="color: #666; margin-top: 10px;">
No PayPal account connected. Check the "Save PayPal" box during checkout to save your PayPal account for faster future purchases.
</p>
{% else %}
<p class="billing-meta">No PayPal account connected. Check the "Save PayPal" box during checkout to save your PayPal account for faster future purchases.</p>
{% endif %}
</section>
{% endif %}
</section>
{% endif %}
<center>
<a href="/cart" class="product-new-button mps-button">Review Order</a>
&nbsp;
&nbsp;
&nbsp;
<a href="/cart/checkout" class="cart-checkout-button mps-button">Checkout</a>
</center>
<section class="billing-actions">
<a href="/cart" class="product-edit-button mps-button">Review Order</a>
<a href="/cart/checkout" class="cart-checkout-button mps-button mps-button-green">Checkout</a>
</section>
</section>
{%- endblock -%}