feat(design): warm↔cool gradient + edge-light response on chips #115
3 changed files with 121 additions and 61 deletions
|
|
@ -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">
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue