Files
PolyWeather/frontend/components/subscription/UnlockProOverlay.module.css
T
2026-03-13 09:34:58 +08:00

743 lines
13 KiB
CSS

/* ── Outer shell ── */
.modal {
position: relative;
width: 100%;
max-width: 820px;
max-height: calc(100dvh - 2.5rem);
overflow-x: hidden;
overflow-y: auto;
/* Hide scrollbar — all browsers */
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none; /* IE / Edge legacy */
border-radius: 28px;
border: 1px solid rgba(255, 255, 255, 0.07);
background: linear-gradient(160deg, #111827 0%, #0d1525 40%, #090f1c 100%);
box-shadow:
0 0 0 1px rgba(255, 255, 255, 0.04),
0 32px 80px -12px rgba(0, 0, 0, 0.8),
0 0 120px -40px rgba(79, 109, 230, 0.28);
padding: 28px 24px 24px;
}
/* Chrome / Safari / WebKit */
.modal::-webkit-scrollbar {
display: none;
}
@media (min-width: 768px) {
.modal {
padding: 36px 36px 28px;
}
}
/* ── Ambient glows (not clipped by modal) ── */
.glowLeft {
pointer-events: none;
position: absolute;
left: -80px;
top: -80px;
width: 280px;
height: 280px;
border-radius: 50%;
background: radial-gradient(
circle,
rgba(59, 130, 246, 0.18) 0%,
transparent 70%
);
}
.glowRight {
pointer-events: none;
position: absolute;
right: -60px;
bottom: -60px;
width: 240px;
height: 240px;
border-radius: 50%;
background: radial-gradient(
circle,
rgba(99, 102, 241, 0.14) 0%,
transparent 70%
);
}
.topLine {
pointer-events: none;
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
width: 60%;
height: 1px;
background: linear-gradient(
90deg,
transparent,
rgba(96, 165, 250, 0.35),
transparent
);
}
/* ── Close button ── */
.closeBtn {
position: absolute;
top: 16px;
right: 16px;
z-index: 20;
display: flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
border-radius: 50%;
border: 1px solid rgba(255, 255, 255, 0.1);
background: rgba(255, 255, 255, 0.05);
color: #64748b;
cursor: pointer;
transition: all 0.2s;
}
.closeBtn:hover {
background: rgba(255, 255, 255, 0.12);
border-color: rgba(255, 255, 255, 0.2);
color: #fff;
}
.closeBtn:active {
transform: scale(0.9);
}
/* ── Header ── */
.header {
position: relative;
z-index: 10;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
margin-bottom: 28px;
}
.badge {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 5px 14px;
border-radius: 999px;
border: 1px solid rgba(251, 191, 36, 0.28);
background: rgba(251, 191, 36, 0.1);
margin-bottom: 18px;
}
.badgeText {
font-size: 10px;
font-weight: 800;
letter-spacing: 0.14em;
text-transform: uppercase;
color: #fbbf24;
}
.title {
font-size: clamp(1.9rem, 5vw, 3rem);
font-weight: 900;
line-height: 1.05;
letter-spacing: -0.02em;
background: linear-gradient(175deg, #fff 20%, #94a3b8 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin: 0;
}
.subtitle {
margin-top: 10px;
font-size: 14px;
line-height: 1.6;
color: #64748b;
max-width: 420px;
}
/* ── Card grid ── */
.grid {
position: relative;
z-index: 10;
display: grid;
grid-template-columns: 1fr;
gap: 14px;
}
@media (min-width: 640px) {
.grid {
grid-template-columns: 1fr 1fr;
}
}
/* ── Plan card ── */
.planCard {
position: relative;
border-radius: 20px;
border: 1px solid rgba(59, 130, 246, 0.3);
background: linear-gradient(
135deg,
rgba(30, 58, 110, 0.55) 0%,
rgba(15, 28, 58, 0.4) 100%
);
padding: 22px;
min-height: 200px;
display: flex;
flex-direction: column;
}
.planCard::before {
content: "";
position: absolute;
inset: 0;
border-radius: 20px;
background: linear-gradient(
135deg,
rgba(59, 130, 246, 0.12) 0%,
transparent 60%
);
pointer-events: none;
}
/* ── Points card (eligible) ── */
.pointsCard {
position: relative;
border-radius: 20px;
border: 1px solid rgba(255, 255, 255, 0.08);
background: rgba(255, 255, 255, 0.03);
padding: 22px;
min-height: 200px;
display: flex;
flex-direction: column;
transition:
border-color 0.3s,
background 0.3s;
}
.pointsCardActive {
border-color: rgba(52, 211, 153, 0.3);
background: linear-gradient(
135deg,
rgba(16, 60, 45, 0.5) 0%,
rgba(5, 30, 22, 0.35) 100%
);
}
.pointsCardActive::before {
content: "";
position: absolute;
inset: 0;
border-radius: 20px;
background: linear-gradient(
135deg,
rgba(52, 211, 153, 0.1) 0%,
transparent 60%
);
pointer-events: none;
}
/* ── Points not-eligible card ── */
.pointsUnavailableCard {
position: relative;
border-radius: 20px;
border: 1px dashed rgba(255, 255, 255, 0.12);
background: rgba(255, 255, 255, 0.02);
padding: 22px;
min-height: 200px;
display: flex;
flex-direction: column;
transition: border-color 0.3s;
}
.pointsUnavailableCard:hover {
border-color: rgba(255, 255, 255, 0.2);
}
/* ── Plan label chip ── */
.planChip {
display: inline-flex;
align-items: center;
gap: 5px;
padding: 4px 10px;
border-radius: 8px;
background: rgba(59, 130, 246, 0.18);
font-size: 10px;
font-weight: 800;
letter-spacing: 0.13em;
text-transform: uppercase;
color: #93c5fd;
width: fit-content;
}
/* ── Price ── */
.price {
font-size: 50px;
font-weight: 900;
line-height: 1;
letter-spacing: -0.03em;
color: #fff;
margin: 10px 0 0;
}
.priceSuffix {
font-size: 13px;
font-weight: 600;
color: #475569;
margin-left: 4px;
}
/* ── Feature list ── */
.featureList {
list-style: none;
margin: 16px 0 0;
padding: 0;
display: flex;
flex-direction: column;
gap: 8px;
}
.featureItem {
display: flex;
align-items: center;
gap: 10px;
font-size: 12.5px;
color: #94a3b8;
}
.featureIcon {
display: flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
flex-shrink: 0;
border-radius: 6px;
background: rgba(59, 130, 246, 0.18);
color: #60a5fa;
}
/* ── Points card header row ── */
.pointsHeader {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 12px;
}
.pointsLabelRow {
display: flex;
align-items: center;
gap: 8px;
}
.pointsIconBox {
display: flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
border-radius: 8px;
background: #1e293b;
color: #475569;
transition:
background 0.2s,
color 0.2s;
}
.pointsIconBoxActive {
background: #10b981;
color: #fff;
}
.pointsLabel {
font-size: 10px;
font-weight: 800;
letter-spacing: 0.13em;
text-transform: uppercase;
color: #475569;
transition: color 0.2s;
}
.pointsLabelActive {
color: #6ee7b7;
}
/* ── Toggle ── */
.toggle {
position: relative;
width: 44px;
height: 24px;
flex-shrink: 0;
border-radius: 999px;
background: #1e293b;
cursor: pointer;
border: none;
transition: background 0.3s;
}
.toggleActive {
background: #10b981;
}
.toggleThumb {
position: absolute;
top: 4px;
left: 4px;
width: 16px;
height: 16px;
border-radius: 50%;
background: #fff;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
transition: transform 0.2s;
}
.toggleThumbActive {
transform: translateX(20px);
}
/* ── Discount amount ── */
.discount {
font-size: 48px;
font-weight: 900;
line-height: 1;
letter-spacing: -0.03em;
color: #334155;
transition: color 0.3s;
}
.discountActive {
color: #34d399;
}
.discountSuffix {
font-size: 10px;
font-weight: 800;
letter-spacing: 0.1em;
text-transform: uppercase;
color: #334155;
margin-left: 6px;
}
.pointsNote {
margin-top: 10px;
font-size: 12px;
line-height: 1.5;
color: #475569;
}
.pointsBalance {
display: flex;
align-items: center;
gap: 5px;
margin-top: 12px;
font-size: 11px;
color: #334155;
}
.balanceNum {
font-weight: 700;
color: #475569;
transition: color 0.2s;
}
.balanceNumActive {
color: #34d399;
}
/* ── Unavailable card content ── */
.unavailTitle {
font-size: 14.5px;
font-weight: 700;
color: #e2e8f0;
margin: 0 0 6px;
}
.unavailDesc {
font-size: 12px;
line-height: 1.6;
color: #475569;
margin: 0;
}
.progressWrap {
margin-top: 16px;
}
.progressHeader {
display: flex;
justify-content: space-between;
font-size: 10px;
color: #334155;
margin-bottom: 5px;
}
.progressTrack {
height: 4px;
border-radius: 999px;
background: rgba(255, 255, 255, 0.06);
overflow: hidden;
}
.progressFill {
height: 100%;
border-radius: 999px;
background: linear-gradient(90deg, #3b82f6, #6366f1);
transition: width 0.5s ease;
}
.unavailCta {
margin-top: auto;
padding-top: 16px;
font-size: 11px;
font-weight: 600;
color: #3b82f6;
display: inline-flex;
align-items: center;
gap: 5px;
text-decoration: none;
transition: color 0.2s;
}
.unavailCta:hover {
color: #60a5fa;
}
/* ── Payment summary box ── */
.summaryBox {
position: relative;
z-index: 10;
margin-top: 18px;
border-radius: 20px;
border: 1px solid rgba(255, 255, 255, 0.07);
background: rgba(255, 255, 255, 0.03);
overflow: hidden;
}
.summaryRow {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 20px;
}
.summaryLabel {
font-size: 10px;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
color: #475569;
margin: 0 0 2px;
}
.summaryOriginal {
font-size: 11px;
color: #334155;
text-decoration: line-through;
}
.summaryAmount {
display: flex;
align-items: baseline;
gap: 5px;
}
.summaryPrice {
font-family: "SF Mono", "Fira Code", "Cascadia Code", monospace;
font-size: 40px;
font-weight: 900;
line-height: 1;
color: #fff;
}
.summaryUnit {
font-size: 11px;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
color: #334155;
}
.summaryDivider {
height: 1px;
background: rgba(255, 255, 255, 0.06);
margin: 0 20px;
}
.ctaWrap {
padding: 12px;
}
/* ── CTA Button ── */
.ctaBtn {
position: relative;
display: flex;
width: 100%;
align-items: center;
justify-content: center;
gap: 10px;
overflow: hidden;
border-radius: 14px;
border: none;
background: linear-gradient(90deg, #2563eb 0%, #4f46e5 100%);
padding: 14px 24px;
font-size: 15px;
font-weight: 700;
color: #fff;
cursor: pointer;
transition: all 0.2s;
box-shadow:
0 0 0 1px rgba(99, 102, 241, 0.5),
0 8px 32px -6px rgba(79, 86, 230, 0.55);
}
.ctaBtn:hover:not(:disabled) {
background: linear-gradient(90deg, #3b82f6 0%, #6366f1 100%);
box-shadow:
0 0 0 1px rgba(99, 102, 241, 0.7),
0 12px 40px -6px rgba(99, 102, 241, 0.65);
transform: translateY(-1px);
}
.ctaBtn:active:not(:disabled) {
transform: scale(0.99);
}
.ctaBtn:disabled {
opacity: 0.6;
cursor: not-allowed;
}
/* Shimmer on hover */
.ctaBtn::after {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(
105deg,
transparent 35%,
rgba(255, 255, 255, 0.12) 50%,
transparent 65%
);
transform: translateX(-100%) skewX(-15deg);
transition: transform 0.6s;
}
.ctaBtn:hover::after {
transform: translateX(100%) skewX(-15deg);
}
/* ── Footer ── */
.footer {
position: relative;
z-index: 10;
margin-top: 14px;
display: flex;
align-items: center;
justify-content: center;
gap: 20px;
font-size: 10px;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
color: #1e293b;
}
.footerLink {
display: inline-flex;
align-items: center;
gap: 5px;
color: inherit;
text-decoration: none;
transition: color 0.2s;
}
.footerLink:hover {
color: #475569;
}
/* ── Alert messages ── */
.alertError {
margin-top: 14px;
display: flex;
align-items: flex-start;
gap: 10px;
border-radius: 12px;
border: 1px solid rgba(239, 68, 68, 0.2);
background: rgba(239, 68, 68, 0.07);
padding: 12px 14px;
font-size: 12px;
line-height: 1.5;
color: #f87171;
}
.alertInfo {
margin-top: 14px;
display: flex;
align-items: flex-start;
gap: 10px;
border-radius: 12px;
border: 1px solid rgba(52, 211, 153, 0.2);
background: rgba(52, 211, 153, 0.07);
padding: 12px 14px;
font-size: 12px;
line-height: 1.5;
color: #6ee7b7;
}
.alertIconBox {
display: flex;
align-items: center;
justify-content: center;
width: 18px;
height: 18px;
flex-shrink: 0;
border-radius: 50%;
margin-top: 1px;
}
.alertIconError {
background: rgba(239, 68, 68, 0.2);
color: #f87171;
}
.alertIconInfo {
background: rgba(52, 211, 153, 0.2);
color: #6ee7b7;
}
/* ── Chip for unavail ── */
.unavailChip {
display: inline-flex;
align-items: center;
gap: 6px;
margin-bottom: 10px;
}
.unavailChipIcon {
display: flex;
align-items: center;
justify-content: center;
width: 26px;
height: 26px;
border-radius: 7px;
background: rgba(255, 255, 255, 0.05);
color: #334155;
transition:
background 0.2s,
color 0.2s;
}
.pointsUnavailableCard:hover .unavailChipIcon {
background: rgba(255, 255, 255, 0.08);
color: #475569;
}
.unavailChipLabel {
font-size: 10px;
font-weight: 800;
letter-spacing: 0.13em;
text-transform: uppercase;
color: #334155;
}