/* Hallmark · genre: modern-minimal · theme: Hutan · motion layer for every page (index, masuk, dashboard, admin)
 * Loaded after ui.css and app.css; motion.js drives the classes. Motion has a job here: show where you went,
 * what arrived and what changed. Only transform and opacity move. Reduced motion is answered at the end.
 */
:root {
  interpolate-size: allow-keywords;
  --ease-pop: cubic-bezier(0.34, 1.4, 0.64, 1);
  --dur-enter: 560ms;
  --stagger: 55ms;
}

/* ------------------------------------------------------------------ page to page (same-origin navigations) */
@view-transition { navigation: auto; }
.nav-pill .wordmark .logo,
.auth-top .wordmark .logo,
.side__brand .logo,
.mtop .wordmark .logo,
.gate__brand .logo { view-transition-name: ym-logo; }
::view-transition-old(root) { animation: 200ms cubic-bezier(0.7, 0, 0.84, 0) both vt-out; }
::view-transition-new(root) { animation: 480ms cubic-bezier(0.16, 1, 0.3, 1) 80ms both vt-in; }
::view-transition-group(ym-logo) { animation-duration: 520ms; animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); }
@keyframes vt-out { to { opacity: 0; transform: translateY(-6px); } }
@keyframes vt-in { from { opacity: 0; transform: translateY(14px); } }

/* ------------------------------------------------------------------ staged entrance and row cascade */
@keyframes st-rise { from { opacity: 0; transform: translateY(14px); } }
@keyframes st-row { from { opacity: 0; transform: translateY(6px); } }
@keyframes ym-fade-in { from { opacity: 0; } }
@keyframes ym-fade-out { to { opacity: 0; } }
.st {
  animation: st-rise var(--dur-enter) var(--ease-out) both;
  animation-delay: calc(min(var(--i, 0), 10) * var(--stagger));
}
.st-row {
  animation: st-row 420ms var(--ease-out) both;
  animation-delay: calc(min(var(--i, 0), 14) * 24ms);
}
/* Single elements that appear (a new order, a demo state, a tab panel). */
.is-entering { animation: st-rise 460ms var(--ease-out) both; }
[role="tabpanel"]:not([hidden]) { animation: ym-fade-in 280ms var(--ease-out); }

/* ------------------------------------------------------------------ scroll reveal (hidden only once JS is running) */
.ym-motion .rv { opacity: 0; transform: translateY(22px); }
.ym-motion .rv.rv-in {
  opacity: 1;
  transform: none;
  transition: opacity 700ms var(--ease-out), transform 800ms var(--ease-out);
  transition-delay: calc(min(var(--i, 0), 8) * 70ms);
}

/* ------------------------------------------------------------------ sliding nav indicator */
.has-ind { position: relative; }
.nav-ind {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
  opacity: 0;
  transition: transform 460ms var(--ease-out), opacity var(--dur-short) var(--ease-out);
}
.nav-ind.is-instant { transition: none; }
.nav-ind--pill {
  border-radius: var(--radius-pill);
  background: var(--color-surface);
  box-shadow: 0 0 0 1px var(--color-rule);
}
.side__nav.has-ind .side__link { position: relative; }
.side__nav.has-ind .side__link[aria-current="page"] { background: transparent; box-shadow: none; }
.nav-ind--bar {
  top: -1px;
  inline-size: var(--space-lg);
  block-size: 2px;
  background: var(--color-accent);
}
.tabbar.has-ind a[aria-current="page"]::before { display: none; }
.tabbar a i { transition: transform 320ms var(--ease-pop); }
.tabbar a[aria-current="page"] i { transform: translateY(-1px); }

/* ------------------------------------------------------------------ press and copy feedback */
.btn:active:not(:disabled) { transform: translateY(1px) scale(0.98); }
.choice, .segmented label { transition: background-color var(--dur-short) var(--ease-out), border-color var(--dur-short) var(--ease-out), box-shadow var(--dur-short) var(--ease-out), transform var(--dur-micro) var(--ease-out); }
.choice:active { transform: scale(0.985); }
[data-state="copied"] .ph.ph-copy::before { content: "\e182"; }
[data-state="copied"] i { animation: pop 380ms var(--ease-pop); }
@keyframes pop { from { transform: scale(0.55); } }

/* ------------------------------------------------------------------ dialogs */
.dialog[open] { animation: dlg-in 360ms var(--ease-out); }
.dialog[open]::backdrop { animation: ym-fade-in 280ms var(--ease-out); }
.dialog.is-closing { animation: dlg-out 150ms var(--ease-in) forwards; }
.dialog.is-closing::backdrop { animation: ym-fade-out 150ms var(--ease-in) forwards; }
@keyframes dlg-in { from { opacity: 0; transform: translateY(14px) scale(0.97); } }
@keyframes dlg-out { to { opacity: 0; transform: translateY(6px) scale(0.98); } }

/* ------------------------------------------------------------------ toasts */
.toast { animation: toast-pop 460ms var(--ease-pop); }
.toast.is-leaving {
  opacity: 0;
  transform: translateY(10px) scale(0.98);
  transition: opacity 200ms var(--ease-in), transform 200ms var(--ease-in);
}
@keyframes toast-pop { from { opacity: 0; transform: translateY(18px) scale(0.96); } }

/* ------------------------------------------------------------------ waiting: shimmer and a listening dot */
.skel { position: relative; overflow: hidden; animation: none; }
.skel::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, color-mix(in oklch, var(--color-surface) 70%, transparent), transparent);
  transform: translateX(-100%);
  animation: shimmer 1.6s var(--ease-in-out) infinite;
}
@keyframes shimmer { to { transform: translateX(100%); } }
.pulse-dot {
  position: relative;
  display: inline-block;
  flex: none;
  inline-size: 8px;
  block-size: 8px;
  border-radius: 50%;
  background: var(--color-accent);
}
.pulse-dot::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: inherit;
  animation: ping 1.8s cubic-bezier(0, 0, 0.2, 1) infinite;
}
@keyframes ping { 70%, 100% { transform: scale(2.8); opacity: 0; } }
.spin-once { display: inline-block; animation: spin-once 700ms var(--ease-out); }
@keyframes spin-once { to { transform: rotate(360deg); } }

/* ------------------------------------------------------------------ code arrival */
.order__code { transition: text-decoration-color 420ms var(--ease-out); }
.order__code.is-decoding { text-decoration-color: transparent; }
.dg {
  display: inline-block;
  min-inline-size: 0.6em;
  text-align: center;
  animation: dg-in 460ms var(--ease-out) both;
  animation-delay: calc(var(--i, 0) * 55ms);
}
@keyframes dg-in { from { opacity: 0; transform: translateY(0.6em) scale(0.9); } }
.is-landed { animation: ym-fade-in 300ms var(--ease-out); }
/* A green edge draws down the card the moment its code lands, then fades. */
.is-arrived { position: relative; }
.is-arrived::before {
  content: "";
  position: absolute;
  top: var(--space-md);
  bottom: var(--space-md);
  left: 0;
  inline-size: 3px;
  border-radius: 0 3px 3px 0;
  background: var(--color-accent);
  transform-origin: top;
  animation: arrive-edge 2s var(--ease-out) forwards;
  pointer-events: none;
}
@keyframes arrive-edge {
  0% { transform: scaleY(0); opacity: 1; }
  22% { transform: scaleY(1); opacity: 1; }
  70% { opacity: 1; }
  100% { transform: scaleY(1); opacity: 0; }
}

/* ------------------------------------------------------------------ meters fill once when their view opens */
.meter.is-filling { animation: meter-in 900ms var(--ease-out) both; }
@keyframes meter-in { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }

/* ------------------------------------------------------------------ forms */
.is-shake { animation: shake 380ms var(--ease-out); }
@keyframes shake {
  20% { transform: translateX(-6px); }
  45% { transform: translateX(5px); }
  70% { transform: translateX(-3px); }
  90% { transform: translateX(1px); }
}
.field__error:not(:empty) { animation: st-row 260ms var(--ease-out); }

/* ------------------------------------------------------------------ disclosure (FAQ) opens with its height */
.faq details::details-content {
  block-size: 0;
  overflow-y: clip;
  transition: block-size 340ms var(--ease-out), content-visibility 340ms allow-discrete;
}
.faq details[open]::details-content { block-size: auto; }
.nav-sheet:not([hidden]) { animation: sheet-in 260ms var(--ease-out); transform-origin: top center; }
@keyframes sheet-in { from { opacity: 0; transform: translateY(-6px) scale(0.98); } }

/* ------------------------------------------------------------------ reduced motion: fades only, nothing travels */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) { animation-name: ym-fade-in; animation-duration: 150ms; animation-delay: 0s; }
  ::view-transition-old(root) { animation-name: ym-fade-out; }
  ::view-transition-group(ym-logo) { animation-duration: 0s; }
  .st, .st-row, .is-entering, .dialog[open], .toast, .is-landed, .nav-sheet:not([hidden]) { animation-name: ym-fade-in; animation-delay: 0s; }
  .dialog.is-closing { animation-name: ym-fade-out; }
  .ym-motion .rv { opacity: 1; transform: none; }
  .nav-ind, .tabbar a i { transition: none; }
  .tabbar a[aria-current="page"] i { transform: none; }
  .btn:active:not(:disabled), .choice:active { transform: none; }
  [data-state="copied"] i, .is-shake, .field__error:not(:empty) { animation: none; }
  .skel::after, .pulse-dot::after, .spin-once, .meter.is-filling, .dg { animation: none; }
  .is-arrived::before { animation: ym-fade-out 2s linear forwards; transform: none; }
  .faq details::details-content { transition: none; }
}
