diff --git a/src/web/components/ClientOverviewPage.jsx b/src/web/components/ClientOverviewPage.jsx index cd6c2b7..8d71c11 100644 --- a/src/web/components/ClientOverviewPage.jsx +++ b/src/web/components/ClientOverviewPage.jsx @@ -95,7 +95,8 @@ function HarborBrand({ isGateway, gatewayAvailable, gatewayDirect, busy, onSetGa Gateway {gatewayDirect ? 'Harbor Gateway активен' : 'Harbor Gateway доступен'} diff --git a/src/web/styles.css b/src/web/styles.css index e29f283..5af9ccf 100644 --- a/src/web/styles.css +++ b/src/web/styles.css @@ -248,22 +248,32 @@ p { .harbor-brand-control:hover .harbor-mode-connect, .harbor-brand-control:focus-visible .harbor-mode-connect { - transform: translateY(-0.14em); + animation: harbor-mode-float-front 1500ms ease-in-out infinite; } .harbor-brand-control:hover .harbor-mode-gateway, .harbor-brand-control:focus-visible .harbor-mode-gateway { - transform: translate(0.42em, 0.5em) scale(0.96); + animation: harbor-mode-float-back 1500ms ease-in-out infinite; } .harbor-brand.is-gateway-active .harbor-brand-control:hover .harbor-mode-connect, .harbor-brand.is-gateway-active .harbor-brand-control:focus-visible .harbor-mode-connect { - transform: translate(0.42em, 0.5em) scale(0.96); + animation-name: harbor-mode-float-back; } .harbor-brand.is-gateway-active .harbor-brand-control:hover .harbor-mode-gateway, .harbor-brand.is-gateway-active .harbor-brand-control:focus-visible .harbor-mode-gateway { - transform: translateY(-0.14em); + animation-name: harbor-mode-float-front; +} + +@keyframes harbor-mode-float-front { + 0%, 100% { transform: translateY(0); } + 50% { transform: translateY(-0.18em); } +} + +@keyframes harbor-mode-float-back { + 0%, 100% { transform: translate(0.42em, 0.34em) scale(0.96); } + 50% { transform: translate(0.42em, 0.58em) scale(0.96); } } .harbor-brand .harbor-mode-swap { @@ -272,13 +282,25 @@ p { left: calc(100% + 4px); width: 14px; height: 14px; - color: var(--harbor-connect); opacity: 0.82; stroke-width: 1.35; transform: translateY(-50%); transition: color 320ms ease, opacity 320ms ease, transform 420ms cubic-bezier(0.16, 1, 0.3, 1); } +.harbor-mode-swap path { + transform-box: fill-box; + transform-origin: center; +} + +.harbor-mode-swap .is-connect { + stroke: var(--harbor-connect); +} + +.harbor-mode-swap .is-gateway { + stroke: var(--harbor-gateway); +} + .harbor-mode-tooltip { position: absolute; bottom: calc(100% + 9px); @@ -318,14 +340,29 @@ p { transition-delay: 120ms, 120ms, 120ms, 0s; } -.harbor-brand.is-gateway-active .harbor-mode-swap { - color: var(--harbor-gateway); -} - .harbor-brand-control:hover .harbor-mode-swap, .harbor-brand-control:focus-visible .harbor-mode-swap { opacity: 1; - transform: translate(1px, -50%); +} + +.harbor-brand-control:hover .harbor-mode-swap .is-connect, +.harbor-brand-control:focus-visible .harbor-mode-swap .is-connect { + animation: harbor-arrow-float-up 1500ms ease-in-out infinite; +} + +.harbor-brand-control:hover .harbor-mode-swap .is-gateway, +.harbor-brand-control:focus-visible .harbor-mode-swap .is-gateway { + animation: harbor-arrow-float-down 1500ms ease-in-out infinite; +} + +@keyframes harbor-arrow-float-up { + 0%, 100% { transform: translateY(0); } + 50% { transform: translateY(-1.5px); } +} + +@keyframes harbor-arrow-float-down { + 0%, 100% { transform: translateY(0); } + 50% { transform: translateY(1.5px); } } .client-instructions-toggle { @@ -946,52 +983,56 @@ p { .client-delete-confirmation { position: absolute; - inset: 0; + top: 50%; + left: 50%; z-index: 2; + width: 100%; + min-height: 250px; display: grid; align-content: center; - gap: 10px; - padding: 28px; + gap: 12px; + padding: 34px; border-radius: 20px; background: color-mix(in oklch, var(--client-panel) 88%, transparent); box-shadow: 0 20px 54px oklch(0.08 0.015 145 / 0.12); backdrop-filter: blur(16px); + transform: translate(-50%, -50%); animation: client-delete-reveal 480ms cubic-bezier(0.16, 1, 0.3, 1) both; } .client-delete-confirmation > span { color: oklch(0.68 0.15 28); - font-size: 9px; + font-size: 10px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; } .client-delete-confirmation h2 { - font-size: 18px; + font-size: 22px; letter-spacing: -0.04em; } .client-delete-confirmation p { color: var(--client-muted); - font-size: 10px; - line-height: 1.65; + font-size: 11px; + line-height: 1.7; } .client-delete-actions { display: flex; justify-content: flex-end; - gap: 8px; - margin-top: 8px; + gap: 10px; + margin-top: 10px; } .client-delete-actions button { - padding: 8px 12px; + padding: 10px 14px; border: 0; border-radius: 9px; background: color-mix(in oklch, var(--client-control) 74%, transparent); color: var(--client-text); - font-size: 10px; + font-size: 11px; font-weight: 700; cursor: pointer; transition: color 220ms ease, background 220ms ease, transform 220ms ease; @@ -1014,8 +1055,8 @@ p { } @keyframes client-delete-reveal { - from { opacity: 0; filter: blur(8px); transform: scale(0.97); } - to { opacity: 1; filter: blur(0); transform: scale(1); } + from { opacity: 0; filter: blur(8px); transform: translate(-50%, -48%) scale(0.97); } + to { opacity: 1; filter: blur(0); transform: translate(-50%, -50%) scale(1); } } .client-form.is-waiting { @@ -1741,7 +1782,7 @@ p { } .client-form { - position: static; + position: relative; width: 100%; transform: none; } @@ -1798,9 +1839,11 @@ p { } .harbor-mode-stack em, + .harbor-mode-swap path, .harbor-brand .harbor-mode-swap, .harbor-mode-tooltip { transition: none; + animation: none; } .client-form-content,