refactor(design): move light response onto chip borders; cut directional drop shadows
Operator feedback 2026-06-04 (after PR #115's two-light-source pass): "A lot of gradients happening, though I want the gradient in the background to be the focus, and then the border gets a highlight, perhaps, in a corner that's closest to the background gradients... the borders are reflecting the color, not necessarily the drop shadows behind the cards. In fact, you could probably reduce those box shadows quite a bit. At least they shouldn't span the entire edge of the card. Just a subtle bit in the corner." PR #115's outer directional drop-shadows (`--edge-light-warm` / `--edge-light-cool`) DID make the chips respond to the two light sources but spanned the entire bottom-left + top-right edges, which competed visually with the body gradient. This PR moves the warm/cool response onto the chip's 1px BORDER, concentrated in the two corners closest to the matching light sources, and cuts the directional drop-shadows entirely (just rim-light-inner + a single neutral elevation-ambient remain). Technique: the modern gradient-border pattern. background: /* surface fill, clipped to padding-box */ linear-gradient(surface, surface) padding-box, /* warm catch-light at bottom-left, border-box-clipped */ radial-gradient(at 0% 100%, warm 0%, transparent 42%) border-box, /* cool catch-light at top-right, border-box-clipped */ radial-gradient(at 100% 0%, cool 0%, transparent 42%) border-box, /* faint diagonal white tint for the rest of the rim */ chip-border-base border-box; border: 1px solid transparent; The transparent border is what exposes the border-box-clipped gradient layers as the visible rim. Token changes (styles/globals.css): - Retired: --edge-light-warm, --edge-light-cool (both themes). These were complete box-shadow declarations with offsets spanning the full bottom-left + top-right edges of every chip. - Added: --corner-light-warm, --corner-light-cool — plain RGBA colors for radial-gradient consumption. Light: 0.50 warm / 0.38 cool. Dark: 0.68 warm / 0.58 cool (bumped so catch-lights read against the deep substrate). - Added: --chip-border-base — faint 135deg white tint so the rest of the rim isn't invisible (sensible chip edge far from either light source). Lower alpha on dark. Application sites: - styles/globals.css `.glass-panel` and `.glass-panel-strong` — updated to multi-layer background + transparent border. Picks up DailyEmberWidget, CommandPaletteModal popover, UserMenu dropdown, the logged-out sidebar Support/Theme tray, etc. - components/Layout.js nav-chip inline style — same treatment. - components/ui/TopSearchBar.js inline style — same treatment. Shadow stacks across all four sites are now just: var(--rim-light-inner), var(--elevation-ambient) (or elevation-pronounced for .glass-panel-strong). The body gradient stays unchanged from PR #115 — it remains the dominant gradient story per operator's "I want the gradient in the background to be the focus" framing. Tests: - npm run test:run: 113/113 - npm run lint: 0 errors (1 pre-existing warning) - npm run build: green Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
c5c31ba813
commit
16685a3522
3 changed files with 109 additions and 65 deletions
|
|
@ -845,24 +845,26 @@ 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. 2026-06-04 two-light-source pass: prepended the
|
{/* Nav chip. 2026-06-04 corner-border pass: same gradient-
|
||||||
two edge-light tokens so the nav chip's bottom-left and
|
border technique as `.glass-panel` — the chip's fill is
|
||||||
top-right edges pick up warm + cool directional glows from
|
clipped to padding-box, and three border-box-clipped
|
||||||
the matching corners of the body gradient — the chip
|
gradient layers expose the warm bottom-left + cool top-
|
||||||
visually "responds" to the two light sources the operator
|
right catch-lights through a 1px transparent border. The
|
||||||
asked for. The chip is positioned at the top-left of the
|
warm/cool drop shadows that lived here through PR #115
|
||||||
viewport so it sits closer to the warm light source; that's
|
are gone — the directional response is on the border
|
||||||
a coincidence of layout, not something the token reacts to,
|
now, not extending into the body gradient. */}
|
||||||
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:
|
||||||
|
'linear-gradient(var(--glass-surface-mid), var(--glass-surface-mid)) padding-box, ' +
|
||||||
|
'radial-gradient(at 0% 100%, var(--corner-light-warm) 0%, transparent 42%) border-box, ' +
|
||||||
|
'radial-gradient(at 100% 0%, var(--corner-light-cool) 0%, transparent 42%) border-box, ' +
|
||||||
|
'var(--chip-border-base) border-box',
|
||||||
|
border: '1px solid transparent',
|
||||||
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:
|
boxShadow: 'var(--rim-light-inner), var(--elevation-ambient)',
|
||||||
'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">
|
||||||
|
|
|
||||||
|
|
@ -312,18 +312,21 @@ export default function TopSearchBar({
|
||||||
// content directly.
|
// content directly.
|
||||||
className="px-4 sm:px-6 py-3 flex items-center gap-3 sm:gap-4 md:rounded-2xl"
|
className="px-4 sm:px-6 py-3 flex items-center gap-3 sm:gap-4 md:rounded-2xl"
|
||||||
style={{
|
style={{
|
||||||
background: 'var(--glass-surface-mid)',
|
// 2026-06-04 corner-border pass: same gradient-border
|
||||||
|
// technique as .glass-panel — the chip's fill clipped to
|
||||||
|
// padding-box, with border-box-clipped warm bottom-left +
|
||||||
|
// cool top-right radial highlights exposed through a 1px
|
||||||
|
// transparent border. The directional outer drop shadows
|
||||||
|
// from PR #115 are gone — corner catch-lights only now.
|
||||||
|
background:
|
||||||
|
'linear-gradient(var(--glass-surface-mid), var(--glass-surface-mid)) padding-box, ' +
|
||||||
|
'radial-gradient(at 0% 100%, var(--corner-light-warm) 0%, transparent 42%) border-box, ' +
|
||||||
|
'radial-gradient(at 100% 0%, var(--corner-light-cool) 0%, transparent 42%) border-box, ' +
|
||||||
|
'var(--chip-border-base) border-box',
|
||||||
|
border: '1px solid transparent',
|
||||||
backdropFilter: 'blur(12px) saturate(180%)',
|
backdropFilter: 'blur(12px) saturate(180%)',
|
||||||
WebkitBackdropFilter: 'blur(12px) saturate(180%)',
|
WebkitBackdropFilter: 'blur(12px) saturate(180%)',
|
||||||
// 2026-06-04 two-light-source pass: prepended edge-light
|
boxShadow: 'var(--rim-light-inner), var(--elevation-ambient)',
|
||||||
// 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
|
||||||
|
|
|
||||||
|
|
@ -201,9 +201,10 @@ body {
|
||||||
|
|
||||||
/* Apply theme colors.
|
/* Apply theme colors.
|
||||||
The hearth gradient: two diagonal light sources that the floating
|
The hearth gradient: two diagonal light sources that the floating
|
||||||
chrome chips visually "respond" to via the --edge-light-warm /
|
chrome chips visually "respond" to via the --corner-light-warm /
|
||||||
--edge-light-cool design tokens (defined further down in :root /
|
--corner-light-cool design tokens (defined further down in :root /
|
||||||
[data-theme="dark"]).
|
[data-theme="dark"]; consumed as radial-gradient layers on each
|
||||||
|
chip's BORDER, not as outer drop shadows — see `.glass-panel`).
|
||||||
- Warm ember light source: bottom-left of the viewport.
|
- Warm ember light source: bottom-left of the viewport.
|
||||||
- Cool purpley-blue light source: top-right of the viewport.
|
- Cool purpley-blue light source: top-right of the viewport.
|
||||||
The base linear-gradient runs along the same 45deg diagonal between
|
The base linear-gradient runs along the same 45deg diagonal between
|
||||||
|
|
@ -231,7 +232,7 @@ body {
|
||||||
),
|
),
|
||||||
/* Purpley-blue pool, top-right — secondary light source (replaces
|
/* Purpley-blue pool, top-right — secondary light source (replaces
|
||||||
the prior gold accent). Indigo→violet so the chip rims that
|
the prior gold accent). Indigo→violet so the chip rims that
|
||||||
respond to this source via --edge-light-cool read as cool. */
|
respond to this source via --corner-light-cool read as cool. */
|
||||||
radial-gradient(
|
radial-gradient(
|
||||||
ellipse 85% 65% at 100% -8%,
|
ellipse 85% 65% at 100% -8%,
|
||||||
rgba(99, 102, 241, 0.42) 0%,
|
rgba(99, 102, 241, 0.42) 0%,
|
||||||
|
|
@ -346,20 +347,32 @@ body {
|
||||||
--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:
|
/* Corner-border light tokens (2026-06-04 refinement of the prior
|
||||||
"let's have the corners or the edges of our sections respond as
|
two-light-source pass — operator feedback: "borders are
|
||||||
if those two are light sources").
|
reflecting the color, not necessarily the drop shadows behind
|
||||||
Each token is a complete box-shadow declaration with the offset
|
the cards. In fact, you could probably reduce those box shadows
|
||||||
pointing toward the matching light source — the colored shadow
|
quite a bit. At least they shouldn't span the entire edge of
|
||||||
bleeds outward from the chip's bottom-left edge (warm) and top-
|
the card. Just a subtle bit in the corner.").
|
||||||
right edge (cool), reading as light catching on the rim.
|
The prior `--edge-light-warm` / `--edge-light-cool` tokens were
|
||||||
Light theme alphas are softer; the dark theme override below
|
complete box-shadow declarations with offsets that spanned the
|
||||||
bumps them since the deeper substrate can absorb more saturation
|
entire bottom-left + top-right edges of every chip. They've
|
||||||
before the effect over-reads. Compose into chip shadow stacks
|
been retired. The replacement is a pair of plain RGBA colors
|
||||||
ahead of rim-light-inner + elevation tokens so the directional
|
consumed by radial-gradient layers in the chip's BACKGROUND
|
||||||
glow is the dominant edge cue. */
|
(border-box-clipped) — see `.glass-panel` below — so the
|
||||||
--edge-light-warm: -6px 6px 18px rgba(255, 110, 0, 0.16);
|
warm/cool light response now reads as a corner-concentrated
|
||||||
--edge-light-cool: 6px -6px 18px rgba(99, 102, 241, 0.12);
|
highlight ON the chip's 1px border, not as an outer drop
|
||||||
|
shadow extending into the body gradient.
|
||||||
|
The `--chip-border-base` is a faint diagonal white tint that
|
||||||
|
paints under the corner gradients so the rest of the rim isn't
|
||||||
|
completely invisible (gives the chip a sensible edge even far
|
||||||
|
from either light source). */
|
||||||
|
--corner-light-warm: rgba(255, 110, 0, 0.50);
|
||||||
|
--corner-light-cool: rgba(99, 102, 241, 0.38);
|
||||||
|
--chip-border-base: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
rgba(255, 255, 255, 0.14) 0%,
|
||||||
|
rgba(255, 255, 255, 0.04) 100%
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dark theme variables */
|
/* Dark theme variables */
|
||||||
|
|
@ -387,12 +400,18 @@ body {
|
||||||
--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
|
/* Dark-theme corner-border colors — alphas bumped so the warm
|
||||||
can take more saturation before reading as garish, and so the
|
and cool catch lights read clearly against the deep substrate.
|
||||||
"lit by ember + lit by purple" effect carries on dark theme (the
|
See :root for the full rationale on the corner-vs-drop-shadow
|
||||||
default for first-time visitors). See :root for full rationale. */
|
refinement. The base white border tint drops in alpha here
|
||||||
--edge-light-warm: -8px 8px 26px rgba(255, 110, 30, 0.34);
|
because the deep canvas absorbs whites more readily. */
|
||||||
--edge-light-cool: 8px -8px 26px rgba(139, 92, 246, 0.28);
|
--corner-light-warm: rgba(255, 130, 30, 0.68);
|
||||||
|
--corner-light-cool: rgba(139, 92, 246, 0.58);
|
||||||
|
--chip-border-base: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
rgba(255, 255, 255, 0.10) 0%,
|
||||||
|
rgba(255, 255, 255, 0.02) 100%
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Custom component styles - Fire-themed */
|
/* Custom component styles - Fire-themed */
|
||||||
|
|
@ -752,35 +771,55 @@ body {
|
||||||
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
|
/* Glass panels — the canonical floating-chrome surface. 2026-06-04
|
||||||
two-light-source pass: `--edge-light-warm` (offset toward bottom-
|
corner-border pass (refines the prior two-light-source pass):
|
||||||
left) and `--edge-light-cool` (offset toward top-right) lead the
|
the warm + cool light response now paints on the chip's 1px
|
||||||
shadow stack so every glass surface picks up the directional rim
|
border using the multi-layer background + transparent-border
|
||||||
glows from the matching corners of the body gradient. Order
|
technique:
|
||||||
matters — directional glows must paint OUTSIDE the structural
|
1. linear-gradient(surface, surface) padding-box — the chip's
|
||||||
elevation shadow, so they sit at the top of the stack (CSS paints
|
translucent fill, clipped to the padding box so it doesn't
|
||||||
the LAST listed shadow lowest visually, but for box-shadow the
|
cover the 1px border ring.
|
||||||
list order doesn't matter for compositing — what matters is each
|
2. radial-gradient(at 0% 100%, warm) border-box — warm corner
|
||||||
shadow's geometry. They're listed warm→cool→rim→elevation as a
|
catch-light, anchored at the chip's bottom-left.
|
||||||
readability convention). */
|
3. radial-gradient(at 100% 0%, cool) border-box — cool corner
|
||||||
|
catch-light, anchored at the chip's top-right.
|
||||||
|
4. --chip-border-base border-box — faint diagonal white tint
|
||||||
|
under the corner gradients so the rest of the rim isn't
|
||||||
|
invisible (gives the chip a sensible edge far from either
|
||||||
|
light source).
|
||||||
|
The `border: 1px solid transparent` is what exposes those
|
||||||
|
border-box-clipped gradient layers as the visible rim.
|
||||||
|
Drop-shadow stack is now just rim-light-inner + elevation —
|
||||||
|
the directional warm/cool outer glows are gone per operator
|
||||||
|
feedback ("reduce those box shadows quite a bit"). */
|
||||||
.glass-panel {
|
.glass-panel {
|
||||||
background: var(--glass-surface-mid);
|
background:
|
||||||
|
linear-gradient(var(--glass-surface-mid), var(--glass-surface-mid))
|
||||||
|
padding-box,
|
||||||
|
radial-gradient(at 0% 100%, var(--corner-light-warm) 0%, transparent 42%)
|
||||||
|
border-box,
|
||||||
|
radial-gradient(at 100% 0%, var(--corner-light-cool) 0%, transparent 42%)
|
||||||
|
border-box,
|
||||||
|
var(--chip-border-base) border-box;
|
||||||
|
border: 1px solid transparent;
|
||||||
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(--elevation-ambient);
|
var(--elevation-ambient);
|
||||||
}
|
}
|
||||||
|
|
||||||
.glass-panel-strong {
|
.glass-panel-strong {
|
||||||
background: var(--glass-surface-high);
|
background:
|
||||||
|
linear-gradient(var(--glass-surface-high), var(--glass-surface-high))
|
||||||
|
padding-box,
|
||||||
|
radial-gradient(at 0% 100%, var(--corner-light-warm) 0%, transparent 42%)
|
||||||
|
border-box,
|
||||||
|
radial-gradient(at 100% 0%, var(--corner-light-cool) 0%, transparent 42%)
|
||||||
|
border-box,
|
||||||
|
var(--chip-border-base) border-box;
|
||||||
|
border: 1px solid transparent;
|
||||||
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(--elevation-pronounced);
|
var(--elevation-pronounced);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue