feat(subscription): add VIP subscription page
Add a new /subscription route showing three VIP membership plans (Monthly, Quarterly, Annual) with a pink→peach banner, per-plan gradient price bars, a benefits card, a mock activate CTA, and an agreement checkbox. - New reusable <Checkbox /> in src/app/_components/core for the legal agreement toggle - Hardcoded SUBSCRIPTION_PLANS constant in src/data/constants - New SubscriptionScreen composed of 7 colocated components (back link, user row, banner, plan card, benefits card, CTA button) with CSS Modules matching the existing design-token system - Route registered as protected and reached from /sidebar "Membership" - Mock CTA: window.alert + router.push(/chat) — no payment calls Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
.card {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: var(--spacing-sm) var(--spacing-xs) 0;
|
||||
background: #ffffff;
|
||||
border: 1px solid transparent;
|
||||
border-radius: var(--radius-lg);
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
transition: border-color 0.15s ease, box-shadow 0.15s ease,
|
||||
transform 0.05s ease;
|
||||
width: 100%;
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.card:focus-visible {
|
||||
outline: 2px solid var(--color-accent);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.card:not(:disabled):active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.highlight {
|
||||
border-color: var(--color-accent);
|
||||
box-shadow: 0 4px 12px rgba(248, 77, 150, 0.18);
|
||||
}
|
||||
|
||||
.selected {
|
||||
border-color: var(--color-accent);
|
||||
border-width: 2px;
|
||||
box-shadow: 0 6px 16px rgba(248, 77, 150, 0.28);
|
||||
}
|
||||
|
||||
.name {
|
||||
margin: 0 0 var(--spacing-xs);
|
||||
font-size: var(--font-size-sm);
|
||||
font-weight: 500;
|
||||
color: var(--color-auth-text-primary);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.priceBlock {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: center;
|
||||
gap: 2px;
|
||||
color: #000;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.currency {
|
||||
font-size: var(--font-size-md);
|
||||
font-weight: 400;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: 28px;
|
||||
font-weight: 300;
|
||||
color: #000;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.originalPrice {
|
||||
margin: 4px 0 var(--spacing-sm);
|
||||
font-size: var(--font-size-xs);
|
||||
color: #999999;
|
||||
text-decoration: line-through;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.perDayBar {
|
||||
align-self: stretch;
|
||||
margin: 0 calc(-1 * var(--spacing-xs)) 0;
|
||||
padding: 6px 0;
|
||||
color: #ffffff;
|
||||
font-size: var(--font-size-xs);
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
line-height: 1.2;
|
||||
}
|
||||
Reference in New Issue
Block a user