From dd8833ee2f5e3c15aa37b5fde403afaca25fc260 Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Thu, 19 Mar 2026 19:28:28 -0400 Subject: [PATCH] Restore visual effects using GPU-safe techniques (no repaint triggers) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- assets/css/dashboard.css | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/assets/css/dashboard.css b/assets/css/dashboard.css index bb9f0e4..b3eea24 100644 --- a/assets/css/dashboard.css +++ b/assets/css/dashboard.css @@ -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 */