From 1507bfc8eb6ad0dfacc46b5cfc6e808a61aaf46a Mon Sep 17 00:00:00 2001 From: Michael Czechowski Date: Tue, 13 Jan 2026 21:17:52 +0100 Subject: [PATCH] fix: make gradient rotate anti-clockwise around border MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use transform: rotate(-360deg) to physically spin the conic-gradient around the preview border. Two layers: - Blurred glow layer (z-index: -2) - Crisp border using mask-composite (z-index: -1) The gradient colors (purple/magenta/cyan/violet) now visually travel anti-clockwise around the border like Gemini's UI. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- src/main.css | 102 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 68 insertions(+), 34 deletions(-) diff --git a/src/main.css b/src/main.css index f45a576..a6ded44 100644 --- a/src/main.css +++ b/src/main.css @@ -596,47 +596,81 @@ kbd { border-radius: var(--border-radius-sm); } -/* Success Match Animation - Gemini-style glowing border */ +/* Success Match Animation - Gemini-style rotating gradient border */ .preview-wrapper.matched { - animation: glow-cycle 2.5s ease-out forwards; + overflow: visible; } -@keyframes glow-cycle { +/* Glow layer (blurred, behind) */ +.preview-wrapper.matched::before { + content: ""; + position: absolute; + inset: -4px; + border-radius: calc(var(--border-radius-md) + 4px); + background: conic-gradient( + from 0deg, + #9b59b6, + #e040fb, + #00bcd4, + #7c4dff, + #9b59b6 + ); + z-index: -2; + filter: blur(12px); + opacity: 0; + animation: rotate-glow 2.5s linear forwards; +} + +/* Border layer (crisp rotating gradient) */ +.preview-wrapper.matched::after { + content: ""; + position: absolute; + inset: -3px; + border-radius: calc(var(--border-radius-md) + 3px); + background: conic-gradient( + from 0deg, + #9b59b6, + #e040fb, + #00bcd4, + #7c4dff, + #9b59b6 + ); + z-index: -1; + -webkit-mask: + linear-gradient(#fff 0 0) content-box, + linear-gradient(#fff 0 0); + -webkit-mask-composite: xor; + mask-composite: exclude; + padding: 3px; + opacity: 0; + animation: rotate-border 2.5s linear forwards; +} + +@keyframes rotate-border { 0% { - box-shadow: - 0 0 0 3px #9b59b6, - 0 0 15px 5px rgba(155, 89, 182, 0.6), - 0 0 30px 10px rgba(155, 89, 182, 0.3); + transform: rotate(0deg); + opacity: 1; } - 25% { - box-shadow: - 0 0 0 3px #e040fb, - 0 0 15px 5px rgba(224, 64, 251, 0.6), - 0 0 30px 10px rgba(224, 64, 251, 0.3); - } - 50% { - box-shadow: - 0 0 0 3px #00bcd4, - 0 0 15px 5px rgba(0, 188, 212, 0.6), - 0 0 30px 10px rgba(0, 188, 212, 0.3); - } - 75% { - box-shadow: - 0 0 0 3px #7c4dff, - 0 0 15px 5px rgba(124, 77, 255, 0.6), - 0 0 30px 10px rgba(124, 77, 255, 0.3); - } - 90% { - box-shadow: - 0 0 0 3px #9b59b6, - 0 0 15px 5px rgba(155, 89, 182, 0.4), - 0 0 30px 10px rgba(155, 89, 182, 0.2); + 80% { + opacity: 1; } 100% { - box-shadow: - 0 0 0 0px transparent, - 0 0 0px 0px transparent, - 0 0 0px 0px transparent; + transform: rotate(-360deg); + opacity: 0; + } +} + +@keyframes rotate-glow { + 0% { + transform: rotate(0deg); + opacity: 0.6; + } + 80% { + opacity: 0.4; + } + 100% { + transform: rotate(-360deg); + opacity: 0; } }