# Motion and interaction ## Motion character Aim for fluid, slightly viscous motion: noticeable, calm, and complete. Avoid bounce, elastic easing, abrupt unmounts, decorative page choreography, or tiny effects too weak to communicate feedback. Use exponential ease-out curves such as `cubic-bezier(0.16, 1, 0.3, 1)` for arrivals. Typical timing: - hover and press: 180-300 ms; - state color and glow: 600-900 ms; - content reveal: 600-850 ms; - numeric tween and progress: about 900 ms; - copy feedback: about 800 ms; - server cascade: 620-760 ms per row with 90-110 ms stagger. ## Power state - Transition gray to green slowly when connecting and green to gray when disconnecting. - Animate icon color, localized light, and SVG shadow together. - Let the light expand and brighten on enable, then contract and fade on disable. - Keep the hit target and all surrounding geometry fixed. - Use a short press compression, followed by a slower release. ## Changing text and numbers - Put alternate labels in fixed-size slots. - Reveal connection title, timer, and hint with opacity plus light blur, never vertical layout movement. - Do not reanimate the timer every second; animate only its initial appearance. - Tween numeric traffic values from old to new with `requestAnimationFrame` or an equivalent stable counter. - Animate progress width concurrently and add a brief glow that fully fades. - Never translate changing numbers if the user asked for a fluid morph; use numerical interpolation, opacity, color, blur, and light. ## Refresh - Use a clean, symmetric SVG refresh icon aligned in the same flex row as its label. - Spin for at least one full cycle. If the request finishes mid-cycle, continue to the next cycle boundary before stopping. - Update data immediately when it arrives; finishing the icon cycle must not delay the data. - Manual refresh may replay meaningful data and server transitions. - Background polling should update quietly and must not repeatedly replay the server cascade. - On updated traffic, tween the number, advance the bar, and emit a visible but brief green flare. ## Server cascade - On initial display, reveal rows from top to bottom with a small negative Y offset, opacity, and blur. - On manual refresh, animate an explicit exit phase first. Fade rows top to bottom, then remount and enter top to bottom. - Wait for the last exit delay and duration before starting entry. - Disable pointer interaction during exit. - Do not replay on ping updates or unrelated renders. ## Subscription input - Show the public domain while retaining the full URL internally. - Disable browser autocomplete suggestions and neutralize autofill backgrounds. - Hide the blinking caret when the paste-first interaction does not need it, while preserving keyboard input and focus outline. - When an existing subscription is being edited and the field is idle, use the green underline as a five-second timeout indicator: start bright, fade to quiet, then restore display mode. - Pause the timeout once the user enters content. - Close and clear unfinished input on outside click or Escape. ## First-run initialization - With no subscription, show only the centered subscription input. Hide power, proxy controls, usage, and servers. - After a valid subscription loads, keep the subscription and server list centered. Require an explicit server choice instead of silently selecting the first server. - On server choice, slide the subscription column to the right while revealing the power column on the viewport's central axis. - Preserve the chosen server on later visits, but return to first-run initialization after subscription deletion. - Deleting a subscription must stop the VPN, clear its cached/configured state, and return the UI to the centered input without leaving stale controls visible. ## Copy feedback - Keep protocol buttons fixed-size and centered. - Copy the complete protocol URL while showing a shared address separately. - Overlay green `Copied` feedback in the same fixed box; do not append text or move the label. - Make feedback appear immediately, hold briefly, and fade fully before restoring the original label. Keep the whole cycle near 800 ms. ## Reduced motion Under `prefers-reduced-motion: reduce`, remove transitions and keyframe animations while preserving final state, focus, color contrast, copy wording, and all functionality.