/*
 * VERTEX motion layer.
 * Interaction patterns are adapted from https://transitions.dev/.
 * The transition recipes may be used and modified in shipped products but
 * must not be redistributed as a competing animation library.
 */

:root {
  --vx-motion-enter: 250ms;
  --vx-motion-exit: 150ms;
  --vx-motion-feedback: 350ms;
  --vx-motion-reveal: 400ms;
  --vx-motion-ease-out: cubic-bezier(.22, 1, .36, 1);
  --vx-motion-ease-standard: cubic-bezier(.2, .8, .2, 1);
  --vx-motion-ease-in: cubic-bezier(.4, 0, 1, 1);
}

/* Menus, popovers and non-modal floating surfaces. */
[data-vx-motion="surface"] {
  --vx-motion-x: 0;
  --vx-motion-y: -4px;
  --vx-motion-scale: .96;
  transform-origin: var(--vx-motion-origin, top right);
  will-change: opacity, transform, filter;
}

[data-vx-motion="surface"][data-vx-motion-state="opening"] {
  opacity: 0;
  transform: translate3d(var(--vx-motion-x), var(--vx-motion-y), 0) scale(var(--vx-motion-scale));
  filter: blur(2px);
  pointer-events: none;
  transition: none;
}

[data-vx-motion="surface"][data-vx-motion-state="open"] {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1);
  filter: blur(0);
  transition:
    opacity var(--vx-motion-enter) var(--vx-motion-ease-out),
    transform var(--vx-motion-enter) var(--vx-motion-ease-out),
    filter var(--vx-motion-enter) var(--vx-motion-ease-out);
}

[data-vx-motion="surface"][data-vx-motion-state="closing"] {
  opacity: 0;
  transform: translate3d(var(--vx-motion-x), calc(var(--vx-motion-y) * .5), 0) scale(.985);
  filter: blur(1px);
  pointer-events: none;
  transition:
    opacity var(--vx-motion-exit) var(--vx-motion-ease-in),
    transform var(--vx-motion-exit) var(--vx-motion-ease-in),
    filter var(--vx-motion-exit) var(--vx-motion-ease-in);
}

[data-vx-motion-kind="context"] {
  --vx-motion-y: -2px;
  --vx-motion-scale: .975;
  --vx-motion-origin: top left;
}

[data-vx-motion-kind="tooltip"] {
  --vx-motion-y: -2px;
  --vx-motion-scale: .985;
  --vx-motion-origin: top center;
}

/* Native dialog entry/exit. */
dialog[data-vx-motion="modal"] {
  transform-origin: center;
  will-change: opacity, transform, filter;
}

dialog[data-vx-motion="modal"][data-vx-motion-state="opening"] {
  opacity: 0;
  transform: translateY(5px) scale(.96);
  filter: blur(3px);
}

dialog[data-vx-motion="modal"][data-vx-motion-state="open"] {
  opacity: 1;
  transform: translateY(0) scale(1);
  filter: blur(0);
  transition:
    opacity var(--vx-motion-enter) var(--vx-motion-ease-out),
    transform var(--vx-motion-enter) var(--vx-motion-ease-out),
    filter var(--vx-motion-enter) var(--vx-motion-ease-out);
}

dialog[data-vx-motion="modal"][data-vx-motion-state="closing"] {
  opacity: 0;
  transform: translateY(3px) scale(.985);
  filter: blur(1px);
  pointer-events: none;
  transition:
    opacity var(--vx-motion-exit) var(--vx-motion-ease-in),
    transform var(--vx-motion-exit) var(--vx-motion-ease-in),
    filter var(--vx-motion-exit) var(--vx-motion-ease-in);
}

dialog[data-vx-motion="modal"]::backdrop {
  opacity: 1;
  transition: opacity var(--vx-motion-enter) var(--vx-motion-ease-out);
}

dialog[data-vx-motion="modal"][data-vx-motion-state="opening"]::backdrop,
dialog[data-vx-motion="modal"][data-vx-motion-state="closing"]::backdrop {
  opacity: 0;
}

/* Sliding tab/segmented-control indicator. */
[data-vx-motion="tabs"] { position: relative; }
[data-vx-motion="tabs"] > :not(.vx-motion-tab-indicator) { position: relative; z-index: 1; }
.vx-motion-tab-indicator {
  position: absolute;
  z-index: 0;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
  border-radius: 5px;
  background: var(--tv-selected, var(--vx-accent-soft, #eef3ff));
  box-shadow: 0 1px 3px rgb(19 23 34 / 10%);
  pointer-events: none;
  transform: translate3d(0, 0, 0);
  transition:
    transform var(--vx-motion-enter) var(--vx-motion-ease-out),
    width var(--vx-motion-enter) var(--vx-motion-ease-out),
    height var(--vx-motion-enter) var(--vx-motion-ease-out),
    opacity var(--vx-motion-exit) ease;
}

[data-vx-motion="tabs"].vx-motion-tabs-underline .vx-motion-tab-indicator {
  height: 2px !important;
  border-radius: 999px;
  background: var(--vx-accent, var(--tv-blue));
  box-shadow: none;
}

[data-vx-motion="tabs"].vx-motion-tabs-ready .active,
[data-vx-motion="tabs"].vx-motion-tabs-ready input:checked + span {
  background: transparent;
  box-shadow: none;
}

[data-vx-motion="tabs"].vx-motion-tabs-underline.vx-motion-tabs-ready .active::after {
  opacity: 0;
}

/* Feedback: badges, text/icon swaps, toasts and errors. */
.notification-badge:not(.hidden),
[data-vx-motion="badge"]:not(.hidden) {
  animation: vx-motion-badge-in var(--vx-motion-feedback) var(--vx-motion-ease-out) both;
  transform-origin: center;
}

@keyframes vx-motion-badge-in {
  0% { opacity: 0; transform: scale(.5); }
  62% { opacity: 1; transform: scale(1.14); }
  100% { opacity: 1; transform: scale(1); }
}

[data-vx-motion="swap"] { will-change: opacity, transform, filter; }
[data-vx-motion="swap"][data-vx-motion-state="out"] {
  opacity: 0;
  transform: translateY(-3px) scale(.96);
  filter: blur(2px);
  transition: opacity 90ms ease, transform 90ms ease, filter 90ms ease;
}
[data-vx-motion="swap"][data-vx-motion-state="in"] {
  animation: vx-motion-swap-in 180ms var(--vx-motion-ease-out) both;
}
@keyframes vx-motion-swap-in {
  from { opacity: 0; transform: translateY(3px) scale(.96); filter: blur(2px); }
  to { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }
}

/* Presence-only feedback never changes layout or an element's own transform. */
[data-vx-motion="presence"] {
  opacity: 1;
  filter: blur(0);
  will-change: opacity, filter;
  transition:
    opacity var(--vx-motion-enter) var(--vx-motion-ease-out),
    filter var(--vx-motion-enter) var(--vx-motion-ease-out);
}
[data-vx-motion="presence"][data-vx-motion-state="opening"] {
  opacity: 0;
  filter: blur(2px);
  transition: none;
}
[data-vx-motion="presence"][data-vx-motion-state="closing"] {
  opacity: 0;
  filter: blur(1px);
  pointer-events: none;
  transition:
    opacity var(--vx-motion-exit) var(--vx-motion-ease-in),
    filter var(--vx-motion-exit) var(--vx-motion-ease-in);
}

/* Native collection updates: only the leading rows stagger to cap paint work. */
[data-vx-motion="list-item"][data-vx-motion-state="entering"] {
  animation: vx-motion-list-item-in 280ms var(--vx-motion-ease-out) both;
  animation-delay: calc(var(--vx-motion-order, 0) * 18ms);
  will-change: opacity, transform, filter;
}
@keyframes vx-motion-list-item-in {
  from { opacity: 0; transform: translateY(5px) scale(.992); filter: blur(1.5px); }
  to { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }
}

.toast-message,
[data-vx-motion="toast"].visible {
  animation: vx-motion-toast-in var(--vx-motion-feedback) var(--vx-motion-ease-out) both;
  will-change: opacity, transform, filter;
}

@keyframes vx-motion-toast-in {
  from { opacity: 0; transform: translate(-50%, 8px) scale(.96); filter: blur(3px); }
  to { opacity: 1; transform: translate(-50%, 0) scale(1); filter: blur(0); }
}

.workspace-save-status[data-vx-motion="toast"] {
  transition:
    opacity var(--vx-motion-exit) ease,
    transform var(--vx-motion-exit) var(--vx-motion-ease-out),
    filter var(--vx-motion-exit) ease;
}
.workspace-save-status[data-vx-motion="toast"]:not(.visible) { filter: blur(2px); }
.workspace-save-status[data-vx-motion="toast"].visible {
  animation-name: vx-motion-status-in;
}
@keyframes vx-motion-status-in {
  from { opacity: 0; transform: translate(-50%, 7px) scale(.97); filter: blur(2px); }
  to { opacity: 1; transform: translate(-50%, 0) scale(1); filter: blur(0); }
}

.login-form--invalid { animation-duration: 320ms; animation-timing-function: var(--vx-motion-ease-standard); }
@keyframes login-denied {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-5px); }
  40% { transform: translateX(5px); }
  60% { transform: translateX(-3px); }
  80% { transform: translateX(3px); }
}

.charting-canvas:not(.related-open) .related-dock-tabs .vx-motion-tab-indicator {
  opacity: 0 !important;
}

/*
 * Docked panels keep their existing grid/flex sizing.  Motion is limited to
 * the host shell so embedded Advanced Charts retain their vendor behaviour.
 */
[data-vx-motion="panel"] {
  --vx-panel-x: 0;
  --vx-panel-y: 0;
  opacity: 1;
  transform: translate3d(0, 0, 0);
  will-change: opacity, transform;
  transition:
    opacity var(--vx-motion-enter) var(--vx-motion-ease-out),
    transform var(--vx-motion-enter) var(--vx-motion-ease-out),
    visibility 0s linear 0s;
}

[data-vx-motion="panel"][data-vx-motion-side="left"] { --vx-panel-x: -7px; }
[data-vx-motion="panel"][data-vx-motion-side="right"] { --vx-panel-x: 7px; }
[data-vx-motion="panel"][data-vx-motion-side="bottom"] { --vx-panel-y: 7px; }

.screener-split.drawer-collapsed > [data-vx-motion="panel"],
.charting-grid.hotlist-collapsed > .chart-hotlist-panel[data-vx-motion="panel"],
.charting-grid.watchlist-collapsed > .native-watchlist[data-vx-motion="panel"],
.charting-grid.info-collapsed > .instrument-info[data-vx-motion="panel"],
.charting-canvas:not(.related-open) .dock-panel-body[data-vx-motion="panel"] {
  opacity: 0;
  visibility: hidden;
  transform: translate3d(var(--vx-panel-x), var(--vx-panel-y), 0);
  pointer-events: none;
  transition:
    opacity var(--vx-motion-exit) var(--vx-motion-ease-in),
    transform var(--vx-motion-exit) var(--vx-motion-ease-in),
    visibility 0s linear var(--vx-motion-exit);
}

/* The persistent 40px dock bar stays still; only its expandable body reveals. */
.related-panel {
  transition: flex-basis var(--vx-motion-enter) var(--vx-motion-ease-out);
}

/* View changes and data replacements use an entry-only reveal to avoid stale exits. */
.market-view.active[data-vx-motion="view"],
.bottom-panel-view.active[data-vx-motion="view"],
.instrument-info-view.active[data-vx-motion="view"],
.plate-flow-members:not(.hidden)[data-vx-motion="view"],
.plate-flow-chart-pane:not(.hidden)[data-vx-motion="view"] {
  animation: vx-motion-view-in var(--vx-motion-enter) var(--vx-motion-ease-out) both;
}

[data-vx-motion="async"]:not(.hidden) {
  animation: vx-motion-async-in var(--vx-motion-reveal) var(--vx-motion-ease-out) both;
}

@keyframes vx-motion-view-in {
  from { opacity: 0; transform: translateY(5px); filter: blur(2px); }
  to { opacity: 1; transform: translateY(0); filter: blur(0); }
}

@keyframes vx-motion-async-in {
  from { opacity: 0; transform: translateY(4px); filter: blur(2px); }
  to { opacity: 1; transform: translateY(0); filter: blur(0); }
}

/* Resizing must track the pointer exactly, without layout or content lag. */
body.resizing-columns .screener-split,
body.resizing-columns .charting-grid,
body.resizing-columns .related-panel,
body.resizing-columns [data-vx-motion="panel"] {
  animation: none !important;
  transition: none !important;
}

/* Mobile panels are absolute overlays, so they can stay mounted for exits. */
@media (max-width: 760px) {
  .screener-split.drawer-collapsed > .chart-drawer[data-vx-motion="panel"],
  .charting-grid.hotlist-collapsed > .chart-hotlist-panel[data-vx-motion="panel"],
  .charting-grid.watchlist-collapsed > .native-watchlist[data-vx-motion="panel"],
  .charting-grid.info-collapsed > .instrument-info[data-vx-motion="panel"] {
    display: flex;
  }
}

/* Async table content crossfades while the skeleton leaves. */
.screener-table-wrap { position: relative; }
.screener-table-wrap::after {
  content: "";
  position: absolute;
  z-index: 6;
  top: 32px;
  right: 0;
  left: 0;
  height: min(304px, calc(100% - 32px));
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  background:
    linear-gradient(90deg, transparent 0%, rgb(255 255 255 / 56%) 48%, transparent 100%) 0 0 / 240px 100% no-repeat,
    repeating-linear-gradient(to bottom, var(--vx-surface) 0 37px, var(--vx-line-subtle) 37px 38px);
  transition:
    opacity var(--vx-motion-reveal) var(--vx-motion-ease-out),
    visibility 0s linear var(--vx-motion-reveal);
}
.screener-table-wrap[aria-busy="true"]::after {
  opacity: 1;
  visibility: visible;
  animation: screener-skeleton-sweep 1.7s ease-in-out infinite;
  transition-delay: 0s;
}
.screener-table-wrap .screener-table tbody {
  opacity: 1;
  filter: blur(0);
  transition:
    opacity var(--vx-motion-reveal) var(--vx-motion-ease-out),
    filter var(--vx-motion-reveal) var(--vx-motion-ease-out);
}
.screener-table-wrap[aria-busy="true"] .screener-table tbody {
  visibility: visible;
  opacity: 0;
  filter: blur(2px);
}

/* Existing carets and common state icons use the same curve. */
[aria-expanded] > .ph-caret-down,
[aria-expanded] > .ph-caret-up,
[aria-expanded] > .ph-caret-left,
[aria-expanded] > .ph-caret-right,
summary > .ph-caret-down,
summary > .ph-caret-up {
  transition: transform var(--vx-motion-enter) var(--vx-motion-ease-out);
}
[aria-expanded="true"] > .ph-caret-down { transform: rotate(180deg); }
[aria-expanded="true"] > .ph-caret-up { transform: rotate(-180deg); }

[data-vx-details-state="closing"] > summary i:last-child { transform: rotate(0deg) !important; }

@media (prefers-reduced-motion: reduce) {
  :root {
    --vx-motion-enter: 1ms;
    --vx-motion-exit: 1ms;
    --vx-motion-feedback: 1ms;
    --vx-motion-reveal: 1ms;
  }
  [data-vx-motion],
  [data-vx-motion]::before,
  [data-vx-motion]::after,
  .toast-message,
  .notification-badge,
  .screener-table-wrap::after,
  .screener-table-wrap .screener-table tbody,
  .related-panel,
  [data-vx-motion="panel"],
  [data-vx-motion="view"],
  [data-vx-motion="async"],
  [data-vx-motion="presence"],
  [data-vx-motion="list-item"] {
    animation: none !important;
    transition: none !important;
    filter: none !important;
  }
}
