/* Whale Admin motion system / 2026-11-09
   Restrained, GPU-friendly interactions. All selectors are admin-scoped.
   No infinite animation on realtime data or input fields. */
body.admin-body{
  --wh-motion-ease:cubic-bezier(.22,1,.36,1);
  --wh-motion-fast:160ms;
  --wh-motion-normal:260ms;
  --wh-motion-enter:440ms;
}
@keyframes wh-page-reveal{
  from{opacity:0;transform:translate3d(0,7px,0)}
  to{opacity:1;transform:translate3d(0,0,0)}
}
@keyframes wh-rail-arrive{
  from{opacity:0;transform:translate3d(-12px,0,0)}
  to{opacity:1;transform:translate3d(0,0,0)}
}
@keyframes wh-dialog-arrive{
  from{opacity:0;transform:translate3d(0,9px,0) scale(.973)}
  to{opacity:1;transform:translate3d(0,0,0) scale(1)}
}
@keyframes wh-center-dialog-arrive{
  from{opacity:0;transform:translate3d(-50%,-48%,0) scale(.975)}
  to{opacity:1;transform:translate3d(-50%,-50%,0) scale(1)}
}
@keyframes wh-backdrop-arrive{
  from{opacity:0}
  to{opacity:1}
}
@keyframes wh-bg-panel-arrive{
  from{opacity:0;transform:translate3d(0,10px,0) scale(.975)}
  to{opacity:1;transform:translate3d(0,0,0) scale(1)}
}
@keyframes wh-filter-change{
  from{opacity:.72;transform:translate3d(0,4px,0)}
  to{opacity:1;transform:translate3d(0,0,0)}
}
@keyframes wh-brand-breathe{
  0%,100%{filter:drop-shadow(0 3px 8px rgba(203,220,230,.13))}
  50%{filter:drop-shadow(0 4px 12px rgba(203,220,230,.32))}
}
/* Depth settle: the WHOLE card comes from nearer the viewer and sits down
   into its final place. Glass blur is constant: no filter or backdrop changes. */
@keyframes wh-depth-settle{
  0%{opacity:0;transform:translate3d(0,-46px,0) scale(1.105)}
  18%{opacity:.14}
  48%{opacity:.70}
  78%{opacity:.97}
  100%{opacity:1;transform:translate3d(0,0,0) scale(1)}
}
body.admin-body .admin-view.wh-motion-enter .wh-depth-card{
  animation:wh-depth-settle 1020ms cubic-bezier(.19,.68,.25,1) both!important;
  animation-delay:var(--wh-depth-delay,0ms)!important;
  transform-origin:center center;
  backface-visibility:hidden;
}
/* Sections without frosted cards (e.g. loading states) still enter as one
   surface; text never moves independently of its panel. */
body.admin-body .admin-view.wh-motion-enter>.wh-depth-section{
  animation:wh-depth-settle 1020ms cubic-bezier(.19,.68,.25,1) both!important;
  animation-delay:var(--wh-depth-delay,0ms)!important;
}
/* Users + commerce: rows descend in a single top-to-bottom wave.
   The frosted table shell stays in place and never scales or moves. */
@keyframes wh-table-row-cascade{
  from{opacity:0}
  to{opacity:1}
}
body.admin-body :is(#usersView,#paymentsView) tbody.wh-rows-prepared > tr:not(.admin-empty-row){opacity:0!important;}
body.admin-body :is(#usersView,#paymentsView) tbody tr.wh-row-cascade{
  animation:wh-table-row-cascade 580ms ease-out both!important;
  animation-delay:var(--wh-row-delay,0ms)!important;
}
/* Old depth classes should never animate an entire list or its glass shell. */
body.admin-body :is(#usersView,#paymentsView) .wh-depth-card,
body.admin-body :is(#usersView,#paymentsView) .wh-depth-section{
  animation:none!important;
}
@media(prefers-reduced-motion:reduce){
  body.admin-body :is(#usersView,#paymentsView) tbody tr.wh-row-cascade{
    animation:none!important;
  }
}

body.admin-body .admin-auth-card{
  animation:wh-dialog-arrive 490ms var(--wh-motion-ease) both;
}
@media(min-width:761px){
  body.admin-body .admin-app.wh-app-enter .admin-sidebar{
    animation:wh-rail-arrive 550ms var(--wh-motion-ease) both;
  }
}
/* Navigation: icon movement, active-state glide, small vertical active marker. */
body.admin-body .admin-nav-item>span{
  transition:transform 250ms var(--wh-motion-ease),opacity 180ms ease!important;
}
body.admin-body .admin-nav-item:hover>span,
body.admin-body .admin-nav-item:focus-visible>span{
  transform:translate3d(0,-1px,0) scale(1.10);
}
body.admin-body .admin-nav-item:active>span{
  transform:scale(.92);
}
body.admin-body .admin-nav-item{
  position:relative;
  transition:background-color 240ms var(--wh-motion-ease),border-color 240ms ease,
    color 220ms ease,box-shadow 260ms var(--wh-motion-ease)!important;
}
@media(min-width:761px){
 body.admin-body .admin-nav-item::before{
   content:'';position:absolute;left:-7px;top:50%;width:3px;height:16px;border-radius:99px;
   background:var(--admin-accent,#e2edf3);
   opacity:0;transform:translate3d(-3px,-50%,0) scaleY(.55);
   transition:opacity 220ms ease,transform 290ms var(--wh-motion-ease),height 290ms var(--wh-motion-ease);
   pointer-events:none;
 }
 body.admin-body .admin-nav-item.is-active::before{
   opacity:1;transform:translate3d(0,-50%,0) scaleY(1);height:22px;
 }
}
/* Buttons: physical press, gentle lift; no shift of the navigation rail. */
body.admin-body :is(.admin-primary,.admin-refresh,.admin-panel-link,
  .admin-filter-group button,.admin-chart-periods button,.admin-chart-series button,
  .admin-subtabs button,.admin-user-tabs button,.admin-user-filters button,
  .admin-users-pagination button,.admin-sort-direction,
  .admin-row-action,.admin-bg-actions button,.admin-bg-close,
  .admin-broadcast-actions button,.admin-reply-send,.admin-ru-refresh,
  .wh-server-copy,.wh-server-password,
  .admin-user-quick-actions button,.admin-user-secondary-actions button,
  .admin-audience-cards button,.admin-action-dialog button,
  .wh-vault-dialog button){
  transition:transform 220ms var(--wh-motion-ease),
    background-color 200ms ease,border-color 200ms ease,
    color 170ms ease,box-shadow 250ms ease!important;
}
@media(hover:hover) and (pointer:fine){
 body.admin-body :is(.admin-primary,.admin-refresh,.admin-panel-link,
   .admin-chart-periods button,.admin-chart-series button,
   .admin-filter-group button,.admin-bg-actions button,
   .admin-broadcast-actions button,.admin-ru-refresh,
   .wh-server-copy,.wh-server-password,
   .admin-action-dialog button,.wh-vault-dialog button):hover:not(:disabled){
   transform:translate3d(0,-1px,0);
 }
}
body.admin-body :is(.admin-primary,.admin-refresh,.admin-panel-link,
  .admin-filter-group button,.admin-chart-periods button,.admin-chart-series button,
  .admin-subtabs button,.admin-user-tabs button,.admin-user-filters button,
  .admin-users-pagination button,.admin-row-action,.admin-bg-actions button,
  .admin-broadcast-actions button,.admin-reply-send,.admin-ru-refresh,
  .wh-server-copy,.wh-server-password,
  .admin-user-quick-actions button,.admin-user-secondary-actions button,
  .admin-action-dialog button,.wh-vault-dialog button):active:not(:disabled){
  transform:scale(.965);
  transition-duration:100ms!important;
}
body.admin-body :is(.admin-chart-periods button,.admin-chart-series button,
  .admin-user-tabs button,.admin-filter-group button,.admin-subtabs button,
  .admin-user-filters button).is-active{
  transition:background-color 280ms ease,border-color 280ms ease,
    color 220ms ease,box-shadow 280ms ease,transform 220ms var(--wh-motion-ease)!important;
}
/* Tables, support inbox and secondary rows get smooth focus transitions. */
body.admin-body :is(.admin-table tbody td,.admin-ticket-item,
  .admin-event-row,.admin-broadcast-item,.admin-quick-list button,
  .admin-overview-stat-list>button,.admin-ru-probe){
  transition:background-color 200ms ease,color 180ms ease,border-color 200ms ease!important;
}
body.admin-body .admin-chart-wrap.wh-motion-update,
body.admin-body .admin-chart-summary.wh-motion-update,
body.admin-body .admin-lte-chart-wrap.wh-motion-update{
  animation:wh-filter-change 290ms var(--wh-motion-ease) both;
}
/* Overview SVG: one continuous line draw, then a soft area/point reveal.
   Do not animate the chart wrapper: its glass surface stays steady. */
@keyframes wh-chart-stroke-draw{
  from{stroke-dashoffset:var(--wh-chart-stroke-length)}
  to{stroke-dashoffset:0}
}
@keyframes wh-chart-area-appear{
  from{opacity:0}
  to{opacity:1}
}
body.admin-body #overviewChart .admin-chart-line.wh-chart-draw{
  animation:wh-chart-stroke-draw 1050ms cubic-bezier(.45,0,.22,1) both;
}
body.admin-body #overviewChart .admin-chart-area.wh-chart-area-reveal{
  animation:wh-chart-area-appear 780ms ease-out 180ms both;
}
body.admin-body #overviewChart .admin-chart-dot.wh-chart-dot-reveal{
  animation:wh-chart-area-appear 400ms ease-out both;
  animation-delay:var(--wh-chart-dot-delay,0ms);
}
@media(prefers-reduced-motion:reduce){
  body.admin-body #overviewChart :is(.wh-chart-draw,.wh-chart-area-reveal,.wh-chart-dot-reveal){animation:none!important}
}

/* Dialogs and popovers get a shared entrance language. */
body.admin-body .admin-action-dialog[open]{
  animation:wh-dialog-arrive 360ms var(--wh-motion-ease) both;
}
body.admin-body .admin-action-dialog[open]::backdrop{
  animation:wh-backdrop-arrive 260ms ease both;
}
body.admin-body .admin-drawer-backdrop:not(.is-hidden){
  animation:wh-backdrop-arrive 250ms ease both;
}
body.admin-body .admin-user-drawer:not(.is-hidden){
  animation:wh-center-dialog-arrive 400ms var(--wh-motion-ease) both;
}
body.admin-body .admin-bg-dialog.is-open .admin-bg-panel{
  transform-origin:95% 100%;
  animation:wh-bg-panel-arrive 360ms var(--wh-motion-ease) both;
}
body.admin-body .wh-vault-backdrop:not([hidden]){
  animation:wh-backdrop-arrive 220ms ease both;
}
body.admin-body .wh-vault-backdrop:not([hidden]) .wh-vault-dialog{
  animation:wh-dialog-arrive 340ms var(--wh-motion-ease) both;
}
/* Glass settings: responsive handle, respecting slider positions. */
@media(hover:hover) and (pointer:fine){
 body.admin-body .admin-glass-control input[type="range"]::-webkit-slider-thumb{
   transition:transform 190ms var(--wh-motion-ease),box-shadow 190ms ease;
 }
 body.admin-body .admin-glass-control input[type="range"]:hover::-webkit-slider-thumb{
   transform:scale(1.13);
 }
 body.admin-body .admin-glass-control input[type="range"]::-moz-range-thumb{
   transition:transform 190ms var(--wh-motion-ease),box-shadow 190ms ease;
 }
 body.admin-body .admin-glass-control input[type="range"]:hover::-moz-range-thumb{
   transform:scale(1.13);
 }
}
/* Live data must remain calm; do not animate frequently reconstructed server cards. */
body.admin-body .wh-server-progress i,
body.admin-body .wh-server-load-track i{
  transition:none!important;
}
/* Accessibility + low power; content and controls remain immediately visible. */
@media(prefers-reduced-motion:reduce){
 body.admin-body *,
 body.admin-body *::before,
 body.admin-body *::after{
   animation-duration:.01ms!important;
   animation-delay:0ms!important;
   animation-iteration-count:1!important;
   transition-duration:.01ms!important;
   scroll-behavior:auto!important;
 }
 body.admin-body .admin-nav-item :is(span),
 body.admin-body :is(button,a):active{
   transform:none!important;
 }
}

/* Keep wallpaper anchored when switching sections with different heights.
   Reserve the vertical scrollbar lane so viewport width does not oscillate. */
/* Scaled entrance cards may extend beyond the viewport: never create an
   extra horizontal scrollbar, while retaining the normal vertical scroll. */
html:has(body.admin-body){overflow-y:scroll;overflow-x:clip;scrollbar-gutter:stable}
body.admin-body{min-height:100dvh;overflow-x:clip}
body.admin-body .admin-app,body.admin-body .admin-main{min-width:0}
body.admin-body::before{background-attachment:fixed!important;transform:translateZ(0);backface-visibility:hidden}

/* Servers: longer, calmer arrival. No sharp scale drop or overlap with
   the loading panel. Glass and all card contents move as one surface. */
@keyframes wh-server-soft-settle{
  0%{opacity:0;transform:translate3d(0,-28px,0) scale(1.072)}
  20%{opacity:.12}
  50%{opacity:.63}
  82%{opacity:.95}
  100%{opacity:1;transform:translate3d(0,0,0) scale(1)}
}
body.admin-body #serversView .wh-server-card.wh-server-enter{
  animation:wh-server-soft-settle 1020ms cubic-bezier(.19,.68,.25,1) both!important;
  animation-delay:var(--wh-depth-delay,0ms)!important;
  transform-origin:center center;
  backface-visibility:hidden;
}
@media(prefers-reduced-motion:reduce){
 body.admin-body .admin-view.wh-motion-enter .wh-depth-card,
 body.admin-body .admin-view.wh-motion-enter>.wh-depth-section,
 body.admin-body #serversView .wh-server-card.wh-server-enter{animation:none!important}
}

/* Quiet first-load state: no fake glass cards or exposed wallpaper grid. */
body.admin-body #serversView.wh-servers-awaiting .admin-ru-section{display:none!important}
body.admin-body #serverStats.wh-server-awaiting{
  display:flex!important;align-items:center;justify-content:center;
  min-height:clamp(220px,48vh,570px);gap:0!important;
}
body.admin-body #serverStats .wh-server-loading-status{
  display:inline-flex;flex-direction:column;align-items:center;justify-content:center;
  gap:15px;color:var(--ui-subtext);font-size:12px;font-weight:500;
  letter-spacing:.01em;text-align:center;
}
body.admin-body #serverStats .wh-server-loading-spinner{
  display:block;width:27px;height:27px;border:2px solid var(--ui-line-soft);
  border-top-color:var(--admin-accent,#bde9f8);border-radius:50%;
  animation:wh-server-spinner 900ms linear infinite;
}
@keyframes wh-server-spinner{to{transform:rotate(360deg)}}
@media(prefers-reduced-motion:reduce){body.admin-body #serverStats .wh-server-loading-spinner{animation:none!important}}
