Restore visual effects using GPU-safe techniques (no repaint triggers)

Rules: transform/opacity = GPU composited (fine). box-shadow/text-shadow on
hover = CPU repaint (removed). Static box-shadow/text-shadow = painted once (fine).

- Buttons (.btn, .btn-base, button, .btn-primary): add will-change:transform
  for pre-promotion, add transform:translateY(-1px) on hover (GPU, no repaint),
  scope transition to include transform, remove box-shadow/text-shadow from hover
- Stat cards: add will-change:transform, add transform:translateY(-2px) on hover
- Priority badges: replace filter:blur(6px) ::after pseudo-element (permanent GPU
  layer per badge, ~20 on screen at once) with static box-shadow:0 0 6px currentColor
  on the badge itself — painted once, never changes, zero compositor overhead
- Links: replace opacity-transition ::after underline (lazy GPU layer creation on
  hover) with text-decoration:underline on hover (pure CPU paint, no GPU layer)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-19 19:28:28 -04:00
parent ab3e77a9ba
commit dd8833ee2f

View File

@@ -251,11 +251,14 @@ h1, h2, h3 {
text-shadow: 0 0 2px currentColor, 0 0 4px currentColor;
}
/* Enhanced link hover with underline animation */
/* Link hover — text-decoration (no opacity pseudo-element, no GPU layer creation) */
a:not(.btn) {
position: relative;
text-decoration: none;
}
a:not(.btn):hover {
text-decoration: underline;
text-underline-offset: 3px;
}
a:not(.btn)::after {
content: '';
@@ -349,20 +352,9 @@ tbody tr {
51%, 100% { opacity: 0; }
}
/* Neon glow effect for priority badges */
/* Neon glow effect for priority badges — static box-shadow (no filter:blur GPU layer) */
.priority-badge {
position: relative;
}
.priority-badge::after {
content: '';
position: absolute;
inset: -2px;
border-radius: inherit;
background: inherit;
filter: blur(6px);
opacity: 0.4;
z-index: -1;
box-shadow: 0 0 6px currentColor;
}
/* Smooth scrollbar styling */
@@ -1605,7 +1597,8 @@ button {
text-transform: uppercase;
font-weight: bold;
position: relative;
transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease, text-shadow 0.2s ease;
will-change: transform;
transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease, transform 0.15s ease;
}
.btn::before,
@@ -1626,13 +1619,13 @@ button:hover {
background: rgba(0, 255, 65, 0.15);
color: var(--terminal-amber);
border-color: var(--terminal-amber);
transform: translateY(-1px);
}
.btn:active,
.btn-base:active,
button:active {
transform: translateY(0);
box-shadow: var(--glow-green-intense);
}
@keyframes pulse-glow-box {
@@ -1663,7 +1656,8 @@ button:active {
font-weight: bold;
font-family: var(--font-mono);
text-transform: uppercase;
transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
will-change: transform;
transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease, transform 0.15s ease;
margin-right: 3.75rem;
}
@@ -1682,6 +1676,7 @@ button:active {
background: rgba(255, 176, 0, 0.1);
color: var(--terminal-green);
border-color: var(--terminal-green);
transform: translateY(-1px);
}
/* ===== RESPONSIVE TICKET CARDS - Hidden on desktop (1400px+) ===== */
@@ -4320,7 +4315,8 @@ tr:hover .quick-actions {
padding: 1rem;
background: linear-gradient(135deg, var(--bg-secondary) 0%, rgba(0, 255, 65, 0.03) 100%);
border: 2px solid var(--terminal-green);
transition: border-color 0.2s ease;
will-change: transform;
transition: border-color 0.2s ease, transform 0.15s ease;
position: relative;
overflow: hidden;
}
@@ -4338,6 +4334,7 @@ tr:hover .quick-actions {
.stat-card:hover {
border-color: var(--terminal-amber);
transform: translateY(-2px);
}
/* Critical stat card styling */