feat(design-system): hearth-gradient body bg + glass page header strips (#100)

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:
varutasu 2026-06-04 09:12:25 -05:00 committed by GitHub
parent 4228a777c6
commit 6d24db1a80
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 68 additions and 7 deletions

View file

@ -49,7 +49,7 @@ export default function CardsPageView(props) {
return (
<>
{/* 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>
<h1 className="text-2xl sm:text-3xl font-bold mb-2" style={{ color: 'var(--text-primary)' }}>

View file

@ -78,7 +78,7 @@ export default function CollectionPageView(props) {
<>
<div className="min-h-screen" style={{ backgroundColor: 'var(--bg-primary)' }}>
{/* 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">
{/* Back button */}
<div className="flex items-center">

View file

@ -48,7 +48,7 @@ export default function CollectionsPageView(props) {
return (
<>
{/* 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>
<h1 className="text-3xl font-bold" style={{ color: 'var(--text-primary)' }}>

View file

@ -198,7 +198,7 @@ export default function CommunityCollections() {
return (
<Layout user={user}>
{/* 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>
<h1 className="text-3xl font-bold" style={{ color: 'var(--text-primary)' }}>

View file

@ -80,7 +80,7 @@ export default function Dashboard() {
return (
<Layout user={user}>
{/* 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>
<h1 className="text-2xl sm:text-3xl font-bold mb-2" style={{ color: 'var(--text-primary)' }}>

View file

@ -262,7 +262,7 @@ export default function MyCards() {
return (
<Layout user={user}>
{/* 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>
<h1 className="text-2xl sm:text-3xl font-bold mb-2" style={{ color: 'var(--text-primary)' }}>

View file

@ -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 {
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);
}
[data-theme="dark"] body {
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);
}
/* .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 */
@keyframes pulse {
0%, 100% {