feat(design): warm↔cool gradient + edge-light response on chips #115

Merged
varutasu merged 1 commit from two-light-source-edge-glow into main 2026-06-04 13:23:22 -04:00
3 changed files with 121 additions and 61 deletions

View file

@ -845,14 +845,24 @@ export default function Layout({ children, user = null, showSearch = false }) {
className="hidden md:flex md:flex-col md:gap-4 w-64" className="hidden md:flex md:flex-col md:gap-4 w-64"
aria-label="Sidebar" aria-label="Sidebar"
> >
{/* Nav chip */} {/* Nav chip. 2026-06-04 two-light-source pass: prepended the
two edge-light tokens so the nav chip's bottom-left and
top-right edges pick up warm + cool directional glows from
the matching corners of the body gradient — the chip
visually "responds" to the two light sources the operator
asked for. The chip is positioned at the top-left of the
viewport so it sits closer to the warm light source; that's
a coincidence of layout, not something the token reacts to,
but the warm glow does naturally read stronger on this chip
because the warm source is right there. */}
<div <div
className="flex-1 flex flex-col md:rounded-3xl md:overflow-hidden min-h-0" className="flex-1 flex flex-col md:rounded-3xl md:overflow-hidden min-h-0"
style={{ style={{
background: 'var(--glass-surface-mid)', background: 'var(--glass-surface-mid)',
backdropFilter: 'blur(var(--glass-blur-mid)) saturate(var(--glass-saturate))', backdropFilter: 'blur(var(--glass-blur-mid)) saturate(var(--glass-saturate))',
WebkitBackdropFilter: 'blur(var(--glass-blur-mid)) saturate(var(--glass-saturate))', WebkitBackdropFilter: 'blur(var(--glass-blur-mid)) saturate(var(--glass-saturate))',
boxShadow: 'var(--rim-light-inner), var(--elevation-ambient)', boxShadow:
'var(--edge-light-warm), var(--edge-light-cool), var(--rim-light-inner), var(--elevation-ambient)',
}} }}
> >
<div className="p-4 h-full flex flex-col w-full"> <div className="p-4 h-full flex flex-col w-full">

View file

@ -315,7 +315,15 @@ export default function TopSearchBar({
background: 'var(--glass-surface-mid)', background: 'var(--glass-surface-mid)',
backdropFilter: 'blur(12px) saturate(180%)', backdropFilter: 'blur(12px) saturate(180%)',
WebkitBackdropFilter: 'blur(12px) saturate(180%)', WebkitBackdropFilter: 'blur(12px) saturate(180%)',
boxShadow: 'var(--rim-light-inner), var(--elevation-ambient)', // 2026-06-04 two-light-source pass: prepended edge-light
// tokens so the header's bottom-left and top-right edges
// pick up warm + cool directional glows. The header sits
// near the top-right of the viewport so the cool source
// reads stronger on it (the purple light is right above);
// the warm rim still appears on the bottom-left edge of the
// chip, just dimmer at this distance from the ember pool.
boxShadow:
'var(--edge-light-warm), var(--edge-light-cool), var(--rim-light-inner), var(--elevation-ambient)',
}} }}
> >
{/* Search affordance — read-only-ish input that opens the {/* Search affordance — read-only-ish input that opens the

View file

@ -200,47 +200,52 @@ body {
} }
/* Apply theme colors. /* Apply theme colors.
The hearth gradient: a soft warm wash that gives glass surfaces a real The hearth gradient: two diagonal light sources that the floating
substrate to blur and distort. Without this the page bg is flat warm- chrome chips visually "respond" to via the --edge-light-warm /
white and the blur is functionally invisible (the chief reason the --edge-light-cool design tokens (defined further down in :root /
first 3 redesign PRs landed but the user said "still looks the same"). [data-theme="dark"]).
Two layers: - Warm ember light source: bottom-left of the viewport.
- A radial ember glow biased to the bottom-left (the seat of a fire) - Cool purpley-blue light source: top-right of the viewport.
- A soft vertical gradient from cooler-top to warmer-bottom The base linear-gradient runs along the same 45deg diagonal between
Fixed attachment so scrolling content slides over the gradient rather the two sources so the page itself reads as a single continuous
than pulling it along — that's what gives glass surfaces their wash, not just two corner pools on a flat substrate. Pushed harder
parallax-blur behavior. */ 2026-06-04 per operator feedback ("increase the gradient in the
background that goes from our nice warm red to a nice purpley
blue") — alphas roughly doubled vs the prior pass, ellipses
enlarged, and the top-right corner switched from gold to
purpley-blue on light theme so both themes carry the same warm↔
cool diagonal story.
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: background-image:
/* Bright amber ember pool, bottom-left — "seat of the fire". */ /* Warm ember pool, bottom-left — primary light source. */
radial-gradient( radial-gradient(
ellipse 75% 55% at 8% 108%, ellipse 90% 65% at 5% 110%,
rgba(255, 110, 0, 0.42) 0%, rgba(255, 95, 0, 0.55) 0%,
rgba(255, 140, 30, 0.22) 28%, rgba(255, 130, 25, 0.28) 28%,
rgba(255, 171, 64, 0.08) 55%, rgba(255, 171, 64, 0.10) 55%,
transparent 78% transparent 80%
), ),
/* Secondary amber, bottom-right — balances wide displays. */ /* Purpley-blue pool, top-right — secondary light source (replaces
the prior gold accent). Indigo→violet so the chip rims that
respond to this source via --edge-light-cool read as cool. */
radial-gradient( radial-gradient(
ellipse 60% 50% at 98% 105%, ellipse 85% 65% at 100% -8%,
rgba(255, 130, 20, 0.30) 0%, rgba(99, 102, 241, 0.42) 0%,
rgba(255, 171, 64, 0.10) 45%, rgba(124, 58, 237, 0.20) 30%,
transparent 72% rgba(167, 139, 250, 0.08) 58%,
transparent 80%
), ),
/* Gold accent, top-right — "smoke catching last light". */ /* Base diagonal wash: warm-cream bottom-left → cool-violet top-right.
radial-gradient( 45deg = bottom-left → top-right (matches the two light sources). */
ellipse 60% 45% at 95% -8%,
rgba(255, 171, 64, 0.24) 0%,
rgba(255, 200, 110, 0.08) 40%,
transparent 68%
),
/* Base wash: cooler-cream top → warmer-amber-tinted bottom. */
linear-gradient( linear-gradient(
180deg, 45deg,
rgba(254, 252, 248, 1) 0%, rgba(255, 240, 220, 1) 0%,
rgba(252, 244, 230, 1) 55%, rgba(252, 244, 230, 1) 50%,
rgba(250, 233, 210, 1) 100% rgba(230, 232, 252, 1) 100%
); );
background-attachment: fixed; background-attachment: fixed;
color: var(--text-primary-light); color: var(--text-primary-light);
@ -249,36 +254,36 @@ body {
[data-theme="dark"] body { [data-theme="dark"] body {
background-color: var(--bg-primary-dark); background-color: var(--bg-primary-dark);
background-image: background-image:
/* Bright ember-red pool, bottom-left — the operator mockup's /* Warm ember-red pool, bottom-left — primary light source.
defining visual. High alpha against deep navy makes it glow. */ Pushed to 0.72 (was 0.55) so the operator's "nice warm red"
reads as a real glow against deep navy. */
radial-gradient( radial-gradient(
ellipse 75% 55% at 8% 108%, ellipse 95% 70% at 5% 110%,
rgba(255, 75, 30, 0.55) 0%, rgba(255, 65, 25, 0.72) 0%,
rgba(255, 110, 0, 0.30) 25%, rgba(255, 95, 0, 0.42) 24%,
rgba(255, 140, 30, 0.10) 55%, rgba(255, 130, 30, 0.16) 52%,
transparent 78% transparent 80%
), ),
/* Secondary ember, bottom-right. */ /* Purpley-blue pool, top-right — secondary light source. Pushed
to 0.58 (was 0.26) + a more saturated indigo→violet ramp so
the corner reads unambiguously as the second light source the
chip rims respond to. */
radial-gradient( radial-gradient(
ellipse 60% 50% at 98% 105%, ellipse 90% 70% at 100% -10%,
rgba(255, 110, 30, 0.36) 0%, rgba(139, 92, 246, 0.58) 0%,
rgba(255, 140, 50, 0.12) 45%, rgba(99, 102, 241, 0.32) 28%,
transparent 72% rgba(168, 85, 247, 0.12) 55%,
transparent 82%
), ),
/* Purple-magenta accent, top-right — the "cosmic" highlight from /* Base diagonal wash: warm-tinted deep aubergine bottom-left →
the mockup's dark variant. Brings TCG/celestial brand energy. */ cool-tinted deep indigo top-right. 45deg matches the light
radial-gradient( sources. The midpoint stays near the previous deep-navy so
ellipse 65% 50% at 95% -8%, chrome surfaces still have a calm substrate to blur against. */
rgba(168, 85, 247, 0.26) 0%,
rgba(124, 58, 237, 0.10) 40%,
transparent 68%
),
/* Subtle vertical wash: pure deep navy → slightly purpler bottom. */
linear-gradient( linear-gradient(
180deg, 45deg,
rgba(13, 14, 26, 1) 0%, rgba(40, 16, 22, 1) 0%,
rgba(17, 18, 38, 1) 55%, rgba(17, 18, 38, 1) 50%,
rgba(22, 18, 45, 1) 100% rgba(28, 22, 58, 1) 100%
); );
background-attachment: fixed; background-attachment: fixed;
color: var(--text-primary-dark); color: var(--text-primary-dark);
@ -340,6 +345,21 @@ body {
--bg-primary-rgb: 254, 252, 248; --bg-primary-rgb: 254, 252, 248;
--bg-secondary-rgb: 247, 243, 237; --bg-secondary-rgb: 247, 243, 237;
--bg-tertiary-rgb: 240, 230, 214; --bg-tertiary-rgb: 240, 230, 214;
/* Two-light-source edge glow tokens (2026-06-04 operator request:
"let's have the corners or the edges of our sections respond as
if those two are light sources").
Each token is a complete box-shadow declaration with the offset
pointing toward the matching light source — the colored shadow
bleeds outward from the chip's bottom-left edge (warm) and top-
right edge (cool), reading as light catching on the rim.
Light theme alphas are softer; the dark theme override below
bumps them since the deeper substrate can absorb more saturation
before the effect over-reads. Compose into chip shadow stacks
ahead of rim-light-inner + elevation tokens so the directional
glow is the dominant edge cue. */
--edge-light-warm: -6px 6px 18px rgba(255, 110, 0, 0.16);
--edge-light-cool: 6px -6px 18px rgba(99, 102, 241, 0.12);
} }
/* Dark theme variables */ /* Dark theme variables */
@ -366,6 +386,13 @@ body {
--input-border: var(--input-border-dark); --input-border: var(--input-border-dark);
--input-text: var(--input-text-dark); --input-text: var(--input-text-dark);
--input-placeholder: var(--input-placeholder-dark); --input-placeholder: var(--input-placeholder-dark);
/* Dark-theme edge glows — alphas bumped since the deeper substrate
can take more saturation before reading as garish, and so the
"lit by ember + lit by purple" effect carries on dark theme (the
default for first-time visitors). See :root for full rationale. */
--edge-light-warm: -8px 8px 26px rgba(255, 110, 30, 0.34);
--edge-light-cool: 8px -8px 26px rgba(139, 92, 246, 0.28);
} }
/* Custom component styles - Fire-themed */ /* Custom component styles - Fire-themed */
@ -724,10 +751,23 @@ body {
only the `-webkit-` form which modern browsers ignore. Write only only the `-webkit-` form which modern browsers ignore. Write only
the unprefixed form; Lightning CSS's autoprefixer adds the prefix the unprefixed form; Lightning CSS's autoprefixer adds the prefix
per browserslist (ios_saf <18 still needs it). */ per browserslist (ios_saf <18 still needs it). */
/* Glass panels — the canonical floating-chrome surface. 2026-06-04
two-light-source pass: `--edge-light-warm` (offset toward bottom-
left) and `--edge-light-cool` (offset toward top-right) lead the
shadow stack so every glass surface picks up the directional rim
glows from the matching corners of the body gradient. Order
matters — directional glows must paint OUTSIDE the structural
elevation shadow, so they sit at the top of the stack (CSS paints
the LAST listed shadow lowest visually, but for box-shadow the
list order doesn't matter for compositing — what matters is each
shadow's geometry. They're listed warm→cool→rim→elevation as a
readability convention). */
.glass-panel { .glass-panel {
background: var(--glass-surface-mid); background: var(--glass-surface-mid);
backdrop-filter: blur(12px) saturate(180%); backdrop-filter: blur(12px) saturate(180%);
box-shadow: box-shadow:
var(--edge-light-warm),
var(--edge-light-cool),
var(--rim-light-inner), var(--rim-light-inner),
var(--rim-light-outer), var(--rim-light-outer),
var(--elevation-ambient); var(--elevation-ambient);
@ -737,6 +777,8 @@ body {
background: var(--glass-surface-high); background: var(--glass-surface-high);
backdrop-filter: blur(20px) saturate(180%); backdrop-filter: blur(20px) saturate(180%);
box-shadow: box-shadow:
var(--edge-light-warm),
var(--edge-light-cool),
var(--rim-light-inner), var(--rim-light-inner),
var(--rim-light-outer), var(--rim-light-outer),
var(--elevation-pronounced); var(--elevation-pronounced);