Fix blink root cause: eliminate position:fixed GPU compositing layers

Chrome promotes ALL position:fixed elements to GPU compositing layers for scroll
performance, regardless of whether they have animations. The body::before scanline
overlay (position:fixed, z-index:9999, full-viewport) and body::after watermark
(position:fixed) were both on GPU layers. Every CPU repaint from any hover state
change required a compositor re-blend pass → one-frame blink at compositor sync.

Fixes:
- Move scanlines from body::before (position:fixed) into body { background-image }
  — same visual, no separate element, no GPU layer promotion
- Set body::before { display:none } and body::after { display:none } in both
  dashboard.css and base.css
- Remove animation:matrix-rain from .stat-card:hover::before — background-position
  animation is not GPU-composited, caused CPU repaints every frame while hovered
  plus GPU texture uploads when animation started/stopped on cursor enter/exit
- Scope a { transition: all } → transition: color in base.css

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-19 12:23:30 -04:00
parent 68ff89b48c
commit ab3e77a9ba
2 changed files with 27 additions and 43 deletions

View File

@@ -96,28 +96,29 @@ body {
margin: 0;
padding: var(--spacing-md);
background-color: var(--bg-primary);
color: var(--text-primary);
position: relative;
}
/* CRT Scanline Effect - Subtle retro terminal look */
body::before {
content: '';
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: repeating-linear-gradient(
/* Scanlines baked into body background — avoids position:fixed GPU layer */
background-image: repeating-linear-gradient(
0deg,
rgba(0, 0, 0, 0.15),
rgba(0, 0, 0, 0.15) 0px,
rgba(0, 0, 0, 0.15) 1px,
transparent 1px,
transparent 2px
);
pointer-events: none;
z-index: var(--z-overlay);
animation: none;
color: var(--text-primary);
position: relative;
}
/* body::before was the CRT scanline overlay (position:fixed, z-index:9999).
Chrome promotes all position:fixed elements to GPU compositing layers, so
every hover-triggered CPU repaint caused a compositor re-blend blink.
Scanlines moved to body background-image above. */
body::before {
display: none;
}
/* Suppress body::after binary text watermark (also position:fixed → GPU layer) */
body::after {
display: none;
}
/* Screen Flicker Effect */
@@ -293,7 +294,6 @@ a:not(.btn):hover::after {
.stat-card:hover::before {
opacity: 1;
animation: matrix-rain 2s linear infinite;
}
@keyframes matrix-rain {