The AtmosphereConf talks your skyline missed
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #24 from musicjunkieg/fix/sharper-glow-contrast

fix: cubic fade + brighter high-glow box-shadow

authored by

chaos gremlin and committed by
GitHub
d4bcfbc1 7436aca9

+39 -16
+7 -5
src/app/globals.css
··· 174 174 } 175 175 176 176 /* Continuous glow for LumeCards — scales with --glow (0–1). 177 - Applied via [style*="--glow"] so it only hits elements with the prop. */ 177 + Applied via [style*="--glow"] so it only hits elements with the prop. 178 + Alphas and spreads are bumped from the original tuning so missed talks 179 + at high glow read as obviously bright rather than just slightly luminous. */ 178 180 [style*="--glow"] { 179 181 box-shadow: 180 - 0 0 calc(16px * var(--glow)) rgba(255, 255, 255, calc(0.25 * var(--glow))), 181 - 0 0 calc(40px * var(--glow)) rgba(180, 255, 215, calc(0.35 * var(--glow))), 182 - 0 0 calc(80px * var(--glow)) rgba(108, 252, 178, calc(0.4 * var(--glow))), 183 - 0 0 calc(120px * var(--glow)) rgba(108, 252, 178, calc(0.2 * var(--glow))); 182 + 0 0 calc(20px * var(--glow)) rgba(255, 255, 255, calc(0.4 * var(--glow))), 183 + 0 0 calc(48px * var(--glow)) rgba(180, 255, 215, calc(0.55 * var(--glow))), 184 + 0 0 calc(96px * var(--glow)) rgba(108, 252, 178, calc(0.6 * var(--glow))), 185 + 0 0 calc(140px * var(--glow)) rgba(108, 252, 178, calc(0.3 * var(--glow))); 184 186 } 185 187 186 188 .ghost-border {
+5 -1
src/components/scored-talks-grid.tsx
··· 33 33 return ( 34 34 <div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3"> 35 35 {scoredTalks.map(({ talk, score }, index) => ( 36 - <Link key={talk.rkey} href={`/talk/${talk.rkey}`}> 36 + <Link 37 + key={talk.rkey} 38 + href={`/talk/${talk.rkey}`} 39 + className="group/card block rounded-lg focus:outline-none focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-primary-fixed" 40 + > 37 41 <LumeCard 38 42 className="h-full" 39 43 glowIntensity={score?.intensity ?? 0}
+27 -10
src/components/ui/lume-card.tsx
··· 48 48 const hasDetail = score && score.state !== "unknown"; 49 49 50 50 // Opacity fades covered talks into the background. 51 - // Range: 1.0 at intensity 1 → 0.2 at intensity 0, with a quadratic curve so 52 - // low-glow (heavily covered) talks fall off fast — at glow 0.3 the card is 53 - // already near 0.27 opacity, at glow 0.7 it's at 0.59. Combined with the 54 - // translucent bg below, this lets covered cards visually recede into the 55 - // page background while missed talks stay vivid. The wider range and steeper 56 - // curve are deliberate: the previous linear 0.5–1.0 range left even fully 57 - // covered cards too solid to read as "faded." 58 - const opacity = 0.2 + glow * glow * 0.8; 51 + // Range: 1.0 at intensity 1 → 0.1 at intensity 0, with a cubic curve so the 52 + // covered zone (low glow) crashes hard while missed talks stay near full 53 + // opacity. Sample points: glow 0.3 → 0.12, glow 0.5 → 0.21, glow 0.7 → 0.41, 54 + // glow 0.9 → 0.76, glow 1.0 → 1.0. The cubic is deliberate — the previous 55 + // quadratic at floor 0.2 still left mid-coverage cards too readable to feel 56 + // like they had visually receded. 57 + const opacity = 0.1 + glow * glow * glow * 0.9; 59 58 60 59 return ( 61 60 <div ··· 73 72 ? "border-primary-fixed-dim/50" 74 73 : "border-primary-fixed-dim/20", 75 74 "transition-[box-shadow,border-color,opacity] duration-500", 75 + // Direct hover/focus/active recovery for when LumeCard is used 76 + // standalone (no wrapping focusable ancestor). 76 77 "hover:biolume-glow-strong hover:!opacity-100", 77 - "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-fixed", 78 + // Recover via a `group/card` ancestor — typically the wrapping 79 + // <Link> in ScoredTalksGrid. Keyboard focus lands on the Link 80 + // (not on this div), so without the named-group plumbing covered 81 + // cards at the cubic floor (~0.10 opacity) would be unreadable 82 + // for keyboard and touch users. group-hover/card duplicates the 83 + // pointer hover path (since hovering the Link also hovers this 84 + // div in practice, but explicit is clearer); group-focus-visible 85 + // /card handles Tab navigation; group-active/card handles touch 86 + // taps where :hover doesn't apply. 87 + "group-hover/card:biolume-glow-strong group-hover/card:!opacity-100", 88 + "group-focus-visible/card:biolume-glow-strong group-focus-visible/card:!opacity-100", 89 + "group-active/card:!opacity-100", 78 90 isUnderstory ? "animate-breathe" : "", 79 91 className, 80 92 ].join(" ")} ··· 107 119 "px-5 pb-3 pt-0", 108 120 // Mobile: always visible (no hover capability) 109 121 "max-h-12 opacity-100", 110 - // Desktop (sm+): hidden by default, revealed on hover via group-hover 122 + // Desktop (sm+): hidden by default, revealed on hover/focus. 123 + // group-hover targets this LumeCard (the unnamed group); 124 + // group-hover/card and group-focus-visible/card target the 125 + // wrapping Link so keyboard tab also reveals the strip. 111 126 "sm:max-h-0 sm:overflow-hidden sm:opacity-0", 112 127 "sm:transition-all sm:duration-300", 113 128 "sm:group-hover:max-h-12 sm:group-hover:opacity-100", 129 + "sm:group-hover/card:max-h-12 sm:group-hover/card:opacity-100", 130 + "sm:group-focus-visible/card:max-h-12 sm:group-focus-visible/card:opacity-100", 114 131 ].join(" ")} 115 132 > 116 133 <div className="border-t border-primary-fixed-dim/20 pt-2">