
:root {
  --motion-fast: 120ms;
  --motion-normal: 180ms;
  --motion-slow: 260ms;
  --motion-card: 200ms;
  --motion-ease: cubic-bezier(.2,.8,.2,1);
  --motion-ease-out: cubic-bezier(.16,1,.3,1);
}

body {
  --workspace-micro-motion: 140ms cubic-bezier(.16,1,.3,1);
}

/* Controls change color/depth without changing their geometry here. */
:is(.button,.btn,.inventory-btn,button[type="submit"]):not(:disabled) {
  transition:
    background-color var(--motion-fast) var(--motion-ease),
    border-color var(--motion-fast) var(--motion-ease),
    color var(--motion-fast) var(--motion-ease),
    box-shadow var(--motion-fast) var(--motion-ease);
}
:is(input,select,textarea,.input,.select) {
  transition:
    border-color var(--motion-fast) var(--motion-ease),
    box-shadow var(--motion-fast) var(--motion-ease),
    background-color var(--motion-fast) var(--motion-ease),
    color var(--motion-fast) var(--motion-ease);
}

/* Functional submit/loading feedback. */
:is(.button,.btn,.inventory-btn,button[type="submit"]).is-submitting {
  position: relative;
  cursor: progress;
  pointer-events: none;
  opacity: 1;
  color: transparent;
  text-shadow: none;
}
:is(.button,.btn,.inventory-btn,button[type="submit"]).is-submitting > * { opacity: 0; }
:is(.button,.btn,.inventory-btn,button[type="submit"]).is-submitting::after {
  content: "";
  position: absolute;
  inset: 50% auto auto 50%;
  width: 16px;
  height: 16px;
  margin: -8px 0 0 -8px;
  border: 2px solid color-mix(in srgb, var(--action-spinner-color, #fff) 30%, transparent);
  border-top-color: var(--action-spinner-color, #fff);
  border-radius: 50%;
  animation: action-spinner .72s linear infinite;
}
@keyframes action-spinner { to { transform: rotate(360deg); } }

:is(.button,.btn,button,input[type="submit"]).is-filtering {
  cursor: progress;
  position: relative;
}
:is(.button,.btn,button,input[type="submit"]).is-filtering::after {
  content: "";
  width: 12px;
  height: 12px;
  margin-inline-start: 7px;
  border: 2px solid currentColor;
  border-inline-end-color: transparent;
  border-radius: 50%;
  display: inline-block;
  vertical-align: -2px;
  animation: gv-control-spin .62s linear infinite;
}
@keyframes gv-control-spin { to { transform: rotate(1turn); } }

/* Save/copy feedback is visual only; no scale/bounce. */
:is(button,input[type="submit"],.button,.btn).is-saved {
  border-color: color-mix(in srgb, var(--p-success, #29845a) 46%, currentColor);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--p-success, #29845a) 18%, transparent);
}
:is(.button,.btn,[data-copy],[data-copy-target],[data-copy-value]).is-copied,
:is([data-copy],[data-copy-target],[data-copy-value],[data-copy-reply]).copied {
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--p-success, #29845a) 22%, transparent);
}
:is([data-copy],[data-copy-target],[data-copy-value],[data-copy-reply]).is-copy-error {
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--p-critical, #c9372c) 18%, transparent);
}

/* Reusable skeleton primitives for real async work only. */
.ui-skeleton {
  position: relative;
  overflow: hidden;
  border-radius: 6px;
  background: color-mix(in srgb, currentColor 8%, transparent);
  color: transparent;
  user-select: none;
}
.ui-skeleton::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, color-mix(in srgb, #fff 45%, transparent), transparent);
  animation: shimmer 1.25s ease-in-out infinite;
}
.ui-skeleton-table,
.ui-skeleton-chart {
  width: 100%;
  min-width: 0;
  display: grid;
  gap: 12px;
}
.ui-skeleton-table { padding: 16px; }
.ui-skeleton-table-row {
  min-width: 0;
  display: grid;
  grid-template-columns: 72px minmax(150px, 1.4fr) repeat(3, minmax(100px, 1fr));
  align-items: center;
  gap: 14px;
}
.ui-skeleton-line { height: 12px; }
.ui-skeleton-line.is-short { width: 58%; }
.ui-skeleton-line.is-tall { height: 18px; }
.ui-skeleton-chart {
  min-height: 220px;
  padding: 20px;
  align-content: end;
  grid-template-columns: repeat(8, minmax(0, 1fr));
  gap: 10px;
}
.ui-skeleton-chart .ui-skeleton { align-self: end; min-height: 44px; }
.ui-skeleton-chart .ui-skeleton:nth-child(2n) { min-height: 92px; }
.ui-skeleton-chart .ui-skeleton:nth-child(3n) { min-height: 138px; }
@keyframes shimmer { to { transform: translateX(100%); } }

/* Focus/selection feedback without movement. */
:is(.service-editor-section,.form-section,.settings-section) {
  transition:
    border-color var(--motion-fast) var(--motion-ease),
    box-shadow var(--motion-fast) var(--motion-ease),
    background-color var(--motion-fast) var(--motion-ease);
}
:is(.service-editor-section,.form-section,.settings-section):focus-within {
  border-color: color-mix(in srgb, var(--p-focus, currentColor) 34%, var(--p-border, transparent));
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--p-focus, currentColor) 7%, transparent);
}
body:not(.gv-vercel-admin) :is(.service-membership-choice,.quick-membership-choice) {
  transition:
    background-color var(--motion-fast) var(--motion-ease),
    border-color var(--motion-fast) var(--motion-ease),
    box-shadow var(--motion-fast) var(--motion-ease);
}
body:not(.gv-vercel-admin) :is(.service-membership-choice,.quick-membership-choice):hover {
  border-color: var(--p-border-hover, currentColor);
  background: var(--p-surface-hover, transparent);
}

/* Validation is functional and immediate. */
:is(input,select,textarea)[aria-invalid="true"] {
  border-color: var(--p-critical, #c9372c);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--p-critical, #c9372c) 18%, transparent);
}
.motion-validation-message {
  display: block;
  margin-top: 5px;
  color: var(--p-critical, #c9372c);
  font-weight:600;
}

/* Status/data colors may transition; their geometry never moves. */
:is(.status,.badge,.status-badge,.notification-tone,.updates-status,[data-status-badge]) {
  transition:
    background-color var(--motion-normal) var(--motion-ease),
    border-color var(--motion-normal) var(--motion-ease),
    color var(--motion-normal) var(--motion-ease),
    box-shadow var(--motion-normal) var(--motion-ease),
    opacity var(--motion-normal) var(--motion-ease);
}

details.ui-disclosure > summary {
  transition:
    background-color var(--motion-fast) var(--motion-ease),
    color var(--motion-fast) var(--motion-ease),
    border-color var(--motion-fast) var(--motion-ease);
}
.motion-sticky-active {
  box-shadow: 0 8px 22px color-mix(in srgb, currentColor 7%, transparent);
  transition: box-shadow var(--motion-normal) var(--motion-ease);
}
:is([data-api-live-bar],#dhruProgressBar,.progress-line > i,.dhru-progress-track > i) {
  transition: width var(--motion-normal) var(--motion-ease-out), background-color var(--motion-normal) var(--motion-ease);
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --motion-fast: 0ms;
    --motion-normal: 0ms;
    --motion-slow: 0ms;
  }
  *, *::before, *::after { scroll-behavior: auto; }
  .ui-skeleton::after,
  :is(.button,.btn,.inventory-btn,button[type="submit"]).is-submitting::after,
  :is(.button,.btn,button,input[type="submit"]).is-filtering::after {
    animation: none;
  }
  :is(input,select,textarea,.input,.select),
  :is(.service-editor-section,.form-section,.settings-section),
  :is(.service-membership-choice,.quick-membership-choice),
  :is(.status,.badge,.status-badge,.notification-tone,.updates-status,[data-status-badge]),
  details.ui-disclosure > summary,
  .motion-sticky-active,
  :is([data-api-live-bar],#dhruProgressBar,.progress-line > i,.dhru-progress-track > i) {
    transition: none;
  }
}

/* Cross-document navigation transition contract. Vercel-style navigation
   keeps geometry fixed and uses only a restrained opacity settle. */
@view-transition { navigation:auto; }
@keyframes gv-page-transition-out {
  to { opacity:.985; }
}
@keyframes gv-page-transition-in {
  from { opacity:.985; }
  to { opacity:1; }
}
::view-transition-old(root) {
  animation:70ms cubic-bezier(.4,0,1,1) both gv-page-transition-out;
}
::view-transition-new(root) {
  animation:120ms cubic-bezier(.16,1,.3,1) both gv-page-transition-in;
}
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) { animation:none; }
}


/* JS fallback for browsers without cross-document View Transitions. The
   canvas never shifts position; it only settles opacity so navigation feels
   immediate instead of jumping between documents. */
@keyframes gv-document-content-enter {
  from { opacity:.985; }
  to { opacity:1; }
}
body.gv-document-enter .app-content-inner {
  animation:120ms cubic-bezier(.16,1,.3,1) both gv-document-content-enter;
}
body.gv-document-leave .app-content-inner {
  opacity:.985;
  transition:opacity 60ms cubic-bezier(.4,0,1,1);
}

@media (prefers-reduced-motion: reduce) {
  body.gv-document-enter .app-content-inner { animation:none; }
  body.gv-document-leave .app-content-inner { transition:none; opacity:1; transform:none; }
}

:is(.field,.form-field,.settings-field,.admin-field,.input-field,.control-group,[data-field]):has(.motion-validation-message) {
  position: relative;
  padding-bottom: 18px;
}
.client-order-field-control:has(.motion-validation-message) {
  position: relative;
  padding-bottom: 18px;
}
.motion-validation-message {
  position: absolute;
  inset-inline-start: 0;
  inset-block-end: 0;
  margin: 0;
  max-width: 100%;
  pointer-events: none;
  font-size: 11px;
  line-height: 1.3;
}
.client-order-field-control > .motion-validation-message {
  inset-inline-start: 2px;
}
