feat(design-system): hearth-gradient body bg + glass page header strips
Three prior PRs (#97 panels, #98 backdrop-filter, #99 box-shadow composition) all landed correct CSS but the user reported the design "still looks the same" on /my-cards and /dashboard. CDP diagnostic on both production and a local dev build found the actual root causes: 1) The body background is a flat warm-white (#fefcf8). Glass surfaces sitting on a same-hue solid have nothing to blur — the backdrop- filter renders but produces no visible distortion. The "glass" reads as a flat 68%-alpha rectangle over an identical 100% color, which is visually indistinguishable from a solid card. 2) Pages with populated data (the user's /my-cards with 2 cards) have ZERO .glass-panel elements after PR #97's sweep. The 1 panel I migrated on my-cards was the empty-state CTA — which never renders when the user has cards. Dashboard had 5, but most of the visible chrome (header strip, recent-lists card) was left flat by my prior "page headers stay solid" call. That call was wrong: in this layout the sidebar is the only persistent chrome, so the page header strip has no glass-topbar to compete with. Fix — two changes that compound: (A) Hearth gradient on body. Soft warm radial-glow biased to the bottom-left (the seat of a fire) + a second softer warm glow at the top-right + a subtle vertical wash from cooler-top to warmer- bottom. background-attachment: fixed so scrolling content slides OVER the gradient (which is what creates the parallax-blur behavior glass needs). Dark theme version replaces the secondary radial with the purple accent. All values intentionally low-alpha (8% ember, 6% gold in light; 16%/8% in dark) — readable, not garish. (B) New .page-header-glass utility for the recurring page-header- strip pattern. tint=high (it spans full content width and needs more visual weight than .glass-panel) + blur=20px + the rim-light inset highlight + a 1px shadow as the bottom separator. Applied via mechanical sweep to the 6 page header strips on: - /my-cards - /dashboard - /community/collections - components/CardsPageView (used by /cards) - components/CollectionsPageView (used by /collections) - components/CollectionPageView (used by /collection/[id]) After this PR, /my-cards (and every other authenticated page) will show a distinctly translucent floating header strip with a soft top highlight against the warm hearth gradient — i.e. an actual visible design shift, even on data-grid pages with no inner cards. Verified locally — npm run build, lint clean, vitest 104/104. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
4228a777c6
commit
57ff215d0d
7 changed files with 68 additions and 7 deletions
|
|
@ -49,7 +49,7 @@ export default function CardsPageView(props) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="p-4 sm:p-6" style={{ backgroundColor: 'var(--bg-secondary)', borderBottom: '1px solid var(--border)' }}>
|
<div className="page-header-glass p-4 sm:p-6">
|
||||||
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-2xl sm:text-3xl font-bold mb-2" style={{ color: 'var(--text-primary)' }}>
|
<h1 className="text-2xl sm:text-3xl font-bold mb-2" style={{ color: 'var(--text-primary)' }}>
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ export default function CollectionPageView(props) {
|
||||||
<>
|
<>
|
||||||
<div className="min-h-screen" style={{ backgroundColor: 'var(--bg-primary)' }}>
|
<div className="min-h-screen" style={{ backgroundColor: 'var(--bg-primary)' }}>
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="p-6 border-b" style={{ backgroundColor: 'var(--bg-secondary)', borderColor: 'var(--border)' }}>
|
<div className="page-header-glass p-6">
|
||||||
<div className="flex items-center justify-between mb-6">
|
<div className="flex items-center justify-between mb-6">
|
||||||
{/* Back button */}
|
{/* Back button */}
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ export default function CollectionsPageView(props) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="p-6" style={{ backgroundColor: 'var(--bg-secondary)', borderBottom: '1px solid var(--border)' }}>
|
<div className="page-header-glass p-6">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-3xl font-bold" style={{ color: 'var(--text-primary)' }}>
|
<h1 className="text-3xl font-bold" style={{ color: 'var(--text-primary)' }}>
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,7 @@ export default function CommunityCollections() {
|
||||||
return (
|
return (
|
||||||
<Layout user={user}>
|
<Layout user={user}>
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="p-6" style={{ backgroundColor: 'var(--bg-secondary)', borderBottom: '1px solid var(--border)' }}>
|
<div className="page-header-glass p-6">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-3xl font-bold" style={{ color: 'var(--text-primary)' }}>
|
<h1 className="text-3xl font-bold" style={{ color: 'var(--text-primary)' }}>
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ export default function Dashboard() {
|
||||||
return (
|
return (
|
||||||
<Layout user={user}>
|
<Layout user={user}>
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="p-4 sm:p-6" style={{ backgroundColor: 'var(--bg-secondary)', borderBottom: '1px solid var(--border)' }}>
|
<div className="page-header-glass p-4 sm:p-6">
|
||||||
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-2xl sm:text-3xl font-bold mb-2" style={{ color: 'var(--text-primary)' }}>
|
<h1 className="text-2xl sm:text-3xl font-bold mb-2" style={{ color: 'var(--text-primary)' }}>
|
||||||
|
|
|
||||||
|
|
@ -262,7 +262,7 @@ export default function MyCards() {
|
||||||
return (
|
return (
|
||||||
<Layout user={user}>
|
<Layout user={user}>
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="p-4 sm:p-6" style={{ backgroundColor: 'var(--bg-secondary)', borderBottom: '1px solid var(--border)' }}>
|
<div className="page-header-glass p-4 sm:p-6">
|
||||||
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-2xl sm:text-3xl font-bold mb-2" style={{ color: 'var(--text-primary)' }}>
|
<h1 className="text-2xl sm:text-3xl font-bold mb-2" style={{ color: 'var(--text-primary)' }}>
|
||||||
|
|
|
||||||
|
|
@ -188,17 +188,78 @@ body {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Apply theme colors */
|
/* Apply theme colors.
|
||||||
|
The hearth gradient: a soft warm wash that gives glass surfaces a real
|
||||||
|
substrate to blur and distort. Without this the page bg is flat warm-
|
||||||
|
white and the blur is functionally invisible (the chief reason the
|
||||||
|
first 3 redesign PRs landed but the user said "still looks the same").
|
||||||
|
Two layers:
|
||||||
|
- A radial ember glow biased to the bottom-left (the seat of a fire)
|
||||||
|
- A soft vertical gradient from cooler-top to warmer-bottom
|
||||||
|
Fixed attachment so scrolling content slides over the gradient rather
|
||||||
|
than pulling it along — that's what gives glass surfaces their
|
||||||
|
parallax-blur behavior. */
|
||||||
body {
|
body {
|
||||||
background-color: var(--bg-primary-light);
|
background-color: var(--bg-primary-light);
|
||||||
|
background-image:
|
||||||
|
radial-gradient(
|
||||||
|
ellipse 80% 60% at 15% 100%,
|
||||||
|
rgba(255, 128, 0, 0.08) 0%,
|
||||||
|
rgba(255, 128, 0, 0.02) 40%,
|
||||||
|
transparent 70%
|
||||||
|
),
|
||||||
|
radial-gradient(
|
||||||
|
ellipse 60% 50% at 85% 0%,
|
||||||
|
rgba(255, 171, 64, 0.06) 0%,
|
||||||
|
transparent 60%
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
180deg,
|
||||||
|
rgba(254, 252, 248, 1) 0%,
|
||||||
|
rgba(252, 246, 235, 1) 100%
|
||||||
|
);
|
||||||
|
background-attachment: fixed;
|
||||||
color: var(--text-primary-light);
|
color: var(--text-primary-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-theme="dark"] body {
|
[data-theme="dark"] body {
|
||||||
background-color: var(--bg-primary-dark);
|
background-color: var(--bg-primary-dark);
|
||||||
|
background-image:
|
||||||
|
radial-gradient(
|
||||||
|
ellipse 80% 60% at 15% 100%,
|
||||||
|
rgba(255, 128, 0, 0.16) 0%,
|
||||||
|
rgba(255, 128, 0, 0.04) 40%,
|
||||||
|
transparent 70%
|
||||||
|
),
|
||||||
|
radial-gradient(
|
||||||
|
ellipse 60% 50% at 85% 0%,
|
||||||
|
rgba(124, 58, 237, 0.08) 0%,
|
||||||
|
transparent 60%
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
180deg,
|
||||||
|
rgba(26, 15, 10, 1) 0%,
|
||||||
|
rgba(38, 22, 14, 1) 100%
|
||||||
|
);
|
||||||
|
background-attachment: fixed;
|
||||||
color: var(--text-primary-dark);
|
color: var(--text-primary-dark);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* .page-header-glass — the recurring "page header strip" pattern
|
||||||
|
(full-bleed band at the top of authenticated pages: dashboard, my-
|
||||||
|
cards, cards, collections, community/collections, collection/[id],
|
||||||
|
scanner). Uses a higher-tint surface than .glass-panel because the
|
||||||
|
strip spans the whole content width and needs more visual weight,
|
||||||
|
but inherits the same rim + blur recipe. Pairs with `border-bottom:
|
||||||
|
1px solid var(--border)` for the separator line below. */
|
||||||
|
.page-header-glass {
|
||||||
|
background: var(--glass-surface-high);
|
||||||
|
backdrop-filter: blur(20px) saturate(180%);
|
||||||
|
box-shadow:
|
||||||
|
var(--rim-light-inner),
|
||||||
|
0 1px 0 var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
/* Card Scanner Animations */
|
/* Card Scanner Animations */
|
||||||
@keyframes pulse {
|
@keyframes pulse {
|
||||||
0%, 100% {
|
0%, 100% {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue