.ui-card { background: var(--card-bg, #FFFFFF); border-radius: 24rpx; padding: 32rpx; margin-bottom: 24rpx; box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.06); box-sizing: border-box; } /* Dark mode: shadows barely read against the darker backdrop, so add a faint bright edge to keep cards elevated and separated from the page. */ @media (prefers-color-scheme: dark) { .ui-card { box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.45), 0 0 0 1rpx rgba(255, 255, 255, 0.04); } } .ui-card--flush { padding: 0; } /* Soft variant: subtle background tint, no shadow */ .ui-card.soft { background: rgba(var(--primary-rgb, 255, 107, 53), 0.04); box-shadow: none; border-radius: 20rpx; } /* Gradient variant: hero card filled with the theme gradient, white text. Descendant elements override --text / --text-secondary locally so any generic text inside automatically flips to white. */ .ui-card.gradient { background: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%); box-shadow: 0 8rpx 28rpx rgba(var(--primary-rgb), 0.35); /* These custom properties are the ONLY channel that crosses the component style-isolation boundary into slotted page content (see MEMORY.md). Any text/fill inside the hero card must read from them, never var(--primary). */ --text: #FFFFFF; --text-secondary: rgba(255, 255, 255, 0.85); --border: rgba(255, 255, 255, 0.28); --on-primary: #FFFFFF; } /* Staggered entrance animation */ .ui-card.in { animation: uiCardIn 0.45s ease both; } .ui-card.in:nth-child(1) { animation-delay: 0.05s; } .ui-card.in:nth-child(2) { animation-delay: 0.15s; } .ui-card.in:nth-child(3) { animation-delay: 0.25s; } .ui-card.in:nth-child(4) { animation-delay: 0.35s; } @keyframes uiCardIn { from { opacity: 0; transform: translateY(40rpx); } to { opacity: 1; transform: translateY(0); } }