diff --git a/src/App.vue b/src/App.vue index c513be7..0f058cd 100644 --- a/src/App.vue +++ b/src/App.vue @@ -133,10 +133,26 @@ const { diff --git a/src/styles/app.css b/src/styles/app.css index 05831c1..4273575 100644 --- a/src/styles/app.css +++ b/src/styles/app.css @@ -173,6 +173,148 @@ padding: 28px; } +.scanning-panel { + justify-items: center; + text-align: center; + overflow: hidden; + background: + radial-gradient(circle at top, rgba(47, 111, 237, 0.16), transparent 38%), + linear-gradient(180deg, rgba(255, 255, 255, 0.88), rgba(243, 247, 252, 0.9)); +} + +.scan-hero { + position: relative; + display: grid; + place-items: center; + width: 148px; + height: 148px; + margin-bottom: 8px; +} + +.scan-core { + position: relative; + display: grid; + place-items: center; + width: 82px; + height: 82px; + border-radius: 50%; + background: linear-gradient(135deg, rgba(255, 255, 255, 0.96), rgba(229, 238, 255, 0.92)); + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.72), + 0 16px 40px rgba(47, 111, 237, 0.14); +} + +.scan-core-ring { + position: absolute; + inset: 12px; + border: 1px solid rgba(47, 111, 237, 0.18); + border-radius: 50%; +} + +.scan-core-ring.secondary { + inset: 22px; + border-color: rgba(16, 24, 40, 0.08); +} + +.scan-orbit { + position: absolute; + inset: 0; + border-radius: 50%; + border: 1px solid rgba(47, 111, 237, 0.12); +} + +.orbit-one { + animation: scan-spin 10s linear infinite; +} + +.orbit-two { + inset: 18px; + border-color: rgba(37, 99, 235, 0.18); + animation: scan-spin-reverse 7.5s linear infinite; +} + +.scan-dot { + position: absolute; + width: 10px; + height: 10px; + border-radius: 50%; + background: linear-gradient(135deg, #2f6fed, #7db4ff); + box-shadow: 0 0 0 6px rgba(47, 111, 237, 0.1); +} + +.dot-one { + top: -4px; +} + +.dot-two { + right: 6px; + bottom: 14px; + width: 8px; + height: 8px; +} + +.dot-three { + left: 10px; + bottom: 10px; + width: 7px; + height: 7px; +} + +.state-panel h2, +.empty-card h3 { + margin: 0; + font-size: 1.12rem; + line-height: 1.2; +} + +.state-panel p, +.empty-card p { + margin: 0; + color: var(--muted); + line-height: 1.55; +} + +.loading-steps { + display: inline-flex; + align-items: center; + gap: 10px; + margin-top: 8px; +} + +.loading-steps span { + width: 36px; + height: 6px; + border-radius: 999px; + background: linear-gradient(90deg, rgba(47, 111, 237, 0.16), rgba(47, 111, 237, 0.44)); + animation: loading-pulse 1.6s ease-in-out infinite; +} + +.loading-steps span:nth-child(2) { + animation-delay: 0.2s; +} + +.loading-steps span:nth-child(3) { + animation-delay: 0.4s; +} + +.empty-card { + min-height: 220px; + place-content: center; + justify-items: center; + padding: 28px; + border: 1px dashed rgba(148, 163, 184, 0.26); + border-radius: 22px; + background: + radial-gradient(circle at top, rgba(47, 111, 237, 0.08), transparent 42%), + linear-gradient(180deg, rgba(255, 255, 255, 0.74), rgba(244, 247, 251, 0.78)); + text-align: center; +} + +.empty-card p { + max-width: 460px; + font-size: 0.94rem; +} + .browser-nav, .styled-scrollbar { scrollbar-width: thin; @@ -200,8 +342,51 @@ background: linear-gradient(180deg, rgba(254, 242, 242, 0.92), rgba(255, 255, 255, 0.86)); } +@keyframes scan-spin { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} + +@keyframes scan-spin-reverse { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(-360deg); + } +} + +@keyframes loading-pulse { + 0%, + 100% { + transform: scaleX(0.82); + opacity: 0.4; + } + + 50% { + transform: scaleX(1); + opacity: 1; + } +} + @media (max-width: 720px) { .sort-bar { justify-content: stretch; } + + .scan-hero { + width: 132px; + height: 132px; + } + + .empty-card { + min-height: 180px; + padding: 22px; + } }