/* Motion for every page (Machine Health, Van Tracker, Settings, sign-in). Loaded after each page's own
   stylesheet. Short and soft: things respond to a press, panels slide and fade rather than appear, numbers
   that change give a small nudge. Nothing here animates on the regular data refreshes, only on what someone
   does (or a value actually changing). Everything is switched off for people who ask for reduced motion. */

:root {
  --ease-out: cubic-bezier(.22, 1, .36, 1);
  --ease-spring: cubic-bezier(.34, 1.4, .64, 1);
  --t-fast: .12s;
  --t-med: .22s;
  --t-slow: .36s;
}

/* ---------- going between pages (Machine Health ⇄ Van Tracker ⇄ Settings) ----------
   All at once, about half a second:
   - the header bar itself stays perfectly still (logo, switcher outline, both labels)
   - the green pill slides from one label to the other, under the labels
   - the controls on the right of the header slide off to the right, and the new page's slide back in
   - the page below cross-fades to the new one */
@view-transition { navigation: auto; }
.topbar { view-transition-name: topbar; }
.app-switch .pill-bg { view-transition-name: app-pill; }
.app-switch .lbl-machines { view-transition-name: lbl-machines; }
.app-switch .lbl-vans { view-transition-name: lbl-vans; }
/* each page's right-hand controls have their own name, so the old set leaves and the new set arrives
   (rather than one morphing into the other) */
.topbar-right.meta-machines { view-transition-name: meta-machines; }
.topbar-right.meta-vans { view-transition-name: meta-vans; }
.topbar-right.meta-settings { view-transition-name: meta-settings; }

::view-transition-group(*) { animation-duration: .5s; animation-timing-function: var(--ease-out); }
/* header bar: no fade at all, it's the same on both pages */
::view-transition-old(topbar) { animation: none; opacity: 0; }
::view-transition-new(topbar) { animation: none; }
/* the pill: the box slides and stretches to the other label; its colour stays solid throughout. Layered
   above the header bar but under both labels, whichever page's markup comes first. */
::view-transition-group(app-pill) { animation-duration: .5s; animation-timing-function: cubic-bezier(.65, 0, .25, 1); z-index: 1; }
::view-transition-group(lbl-machines), ::view-transition-group(lbl-vans) { z-index: 2; }
::view-transition-old(app-pill) { animation: none; opacity: 0; }
::view-transition-new(app-pill) { animation: none; width: 100%; height: 100%; }
/* labels: stay where they are, the text colour cross-fades (white on the pill, grey off it) */
::view-transition-old(lbl-machines), ::view-transition-old(lbl-vans) { animation: vt-fade-out .35s ease both; }
::view-transition-new(lbl-machines), ::view-transition-new(lbl-vans) { animation: vt-fade-in .35s ease .1s both; }
/* right-hand controls: old set off to the right, new set in from the right just behind it */
::view-transition-old(meta-machines), ::view-transition-old(meta-vans), ::view-transition-old(meta-settings) {
  animation: meta-out .28s cubic-bezier(.55, 0, 1, .45) both;
}
::view-transition-new(meta-machines), ::view-transition-new(meta-vans), ::view-transition-new(meta-settings) {
  animation: meta-in .42s var(--ease-out) .18s both;
}
/* the page below: cross-fades over the same half second */
::view-transition-old(root) { animation: vt-fade-out .3s ease both; }
::view-transition-new(root) { animation: vt-fade-in .4s ease .08s both; }
@keyframes vt-fade-out { to { opacity: 0; } }
@keyframes vt-fade-in { from { opacity: 0; } }
@keyframes meta-out { to { transform: translateX(calc(100% + 32px)); opacity: 0; } }
@keyframes meta-in { from { transform: translateX(calc(100% + 32px)); opacity: 0; } }

/* Firefox (no page-to-page transitions): the whole page fades out, then the next one fades in (played by
   motion.js). The page background stays put, so it's a clean dip rather than a flash. */
html.switch-leave body { animation: vt-fade-out .15s ease both; }
html.switch-arrive body { animation: vt-fade-in .3s ease both; }

/* ---------- presses, hovers ---------- */
.btn, .chip, .app-switch a, .seg button, .copy-btn, .link-btn, .back-btn, .rank-open,
#search, select, input[type="text"], input[type="number"], input[type="password"], textarea {
  transition: background-color var(--t-med) var(--ease-out), border-color var(--t-med) var(--ease-out),
    color var(--t-med) var(--ease-out), box-shadow var(--t-med) var(--ease-out), transform var(--t-med) var(--ease-spring),
    outline-color var(--t-med) var(--ease-out);
}
.btn:active:not(:disabled), .chip:active, .app-switch a:active, .seg button:active, .copy-btn:active, .back-btn:active {
  transform: scale(.95);
  transition-duration: .06s;
}
.btn.primary:hover:not(:disabled), #refresh:hover:not(:disabled) { box-shadow: 0 4px 14px color-mix(in srgb, var(--primary) 35%, transparent); }
#search:focus, select:focus, input:focus-visible { box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 22%, transparent); }

/* summary tiles: lift on hover, press down, a soft glow when picked */
.tile {
  transition: transform var(--t-med) var(--ease-spring), box-shadow var(--t-med) var(--ease-out),
    border-color var(--t-med) var(--ease-out), background-color var(--t-med) var(--ease-out),
    outline-color var(--t-med) var(--ease-out), opacity var(--t-slow) var(--ease-out), translate var(--t-slow) var(--ease-out);
}
.tile:hover { transform: translateY(-2px); box-shadow: 0 8px 22px rgba(17, 31, 45, .10); }
.tile:active { transform: translateY(0) scale(.97); transition-duration: .06s; }
.tile.active { box-shadow: 0 6px 20px color-mix(in srgb, var(--primary) 18%, transparent); }
/* a count that changed (set by motion.js) */
.tile-value.bump { animation: bump .5s var(--ease-out); }
@keyframes bump {
  30% { transform: translateY(-3px) scale(1.12); color: var(--accent); }
  100% { transform: none; }
}
/* tiles fade up as the page opens (and when one is shown later, e.g. Battery) */
@starting-style { .tile { opacity: 0; translate: 0 8px; } }
.tiles > .tile:nth-child(2) { transition-delay: 0s, 0s, 0s, 0s, 0s, .03s, .03s; }
.tiles > .tile:nth-child(3) { transition-delay: 0s, 0s, 0s, 0s, 0s, .06s, .06s; }
.tiles > .tile:nth-child(4) { transition-delay: 0s, 0s, 0s, 0s, 0s, .09s, .09s; }
.tiles > .tile:nth-child(5) { transition-delay: 0s, 0s, 0s, 0s, 0s, .12s, .12s; }
.tiles > .tile:nth-child(6) { transition-delay: 0s, 0s, 0s, 0s, 0s, .15s, .15s; }
.tiles > .tile:nth-child(7) { transition-delay: 0s, 0s, 0s, 0s, 0s, .18s, .18s; }
.tiles > .tile:nth-child(8) { transition-delay: 0s, 0s, 0s, 0s, 0s, .21s, .21s; }
.tiles > .tile:nth-child(n+9) { transition-delay: 0s, 0s, 0s, 0s, 0s, .24s, .24s; }

/* rows: hover fades in rather than snapping */
tbody tr, .van-row, .feed li, .stops li, .rank-list li, .cleared-table tbody tr { transition: background-color var(--t-med) var(--ease-out), box-shadow var(--t-med) var(--ease-out); }
.van-row:active { background: color-mix(in srgb, var(--primary) 12%, var(--hover)); }
/* machine list after a filter or sort click: the first rows ripple in (the rest just appear) */
tbody.rows-in > tr, .van-list.rows-in > li { animation: row-in .32s var(--ease-out) both; }
.van-list.rows-in > li:nth-child(2) { animation-delay: .025s; }
.van-list.rows-in > li:nth-child(3) { animation-delay: .05s; }
.van-list.rows-in > li:nth-child(4) { animation-delay: .075s; }
.van-list.rows-in > li:nth-child(5) { animation-delay: .1s; }
.van-list.rows-in > li:nth-child(n+6) { animation-delay: .125s; }
tbody.rows-in > tr:nth-child(2) { animation-delay: .02s; }
tbody.rows-in > tr:nth-child(3) { animation-delay: .04s; }
tbody.rows-in > tr:nth-child(4) { animation-delay: .06s; }
tbody.rows-in > tr:nth-child(5) { animation-delay: .08s; }
tbody.rows-in > tr:nth-child(6) { animation-delay: .1s; }
tbody.rows-in > tr:nth-child(7) { animation-delay: .12s; }
tbody.rows-in > tr:nth-child(8) { animation-delay: .14s; }
tbody.rows-in > tr:nth-child(n+9) { animation-delay: .16s; }
@keyframes row-in { from { opacity: 0; transform: translateY(4px); } }

/* ---------- things that appear (banners, the van panel, lists switching) ---------- */
.banner, .list-view, .van-view, .table-wrap, .savebar, .panel, .login-card, .field-error {
  transition: opacity var(--t-slow) var(--ease-out), translate var(--t-slow) var(--ease-out);
}
@starting-style {
  .banner, .table-wrap, .panel, .field-error { opacity: 0; translate: 0 6px; }
  .van-view { opacity: 0; translate: 14px 0; }
  .list-view { opacity: 0; translate: -14px 0; }
  .savebar { opacity: 0; translate: 0 100%; }
  .login-card { opacity: 0; translate: 0 14px; }
}
.field-error:not([hidden]) { animation: shake .4s var(--ease-out); }
@keyframes shake { 20%, 60% { transform: translateX(-5px); } 40%, 80% { transform: translateX(5px); } }

/* ---------- machine panel (drawer) ---------- */
.drawer { transition: transform var(--t-slow) var(--ease-out); }
.scrim {
  opacity: 1;
  transition: opacity var(--t-slow) var(--ease-out), display var(--t-slow) allow-discrete;
}
.scrim[hidden] { opacity: 0; }
@starting-style { .scrim { opacity: 0; } }
/* Its sections rise in one after another as it opens (motion.js / app.js add .opening for a moment) */
.drawer.opening .drawer-head > *, .drawer.opening .drawer-body > * { animation: rise .45s var(--ease-out) both; }
.drawer.opening .drawer-body > :nth-child(1) { animation-delay: .04s; }
.drawer.opening .drawer-body > :nth-child(2) { animation-delay: .08s; }
.drawer.opening .drawer-body > :nth-child(3) { animation-delay: .12s; }
.drawer.opening .drawer-body > :nth-child(4) { animation-delay: .16s; }
.drawer.opening .drawer-body > :nth-child(n+5) { animation-delay: .2s; }
@keyframes rise { from { opacity: 0; transform: translateY(10px); } }
/* Recent alerts / Recent sales switch: the newly shown list rises in */
.tab-in { animation: rise .3s var(--ease-out) both; }
/* the sales chart's bars grow up when a machine is first opened */
.ch-wrap.grow .ch-bar { transform-box: fill-box; transform-origin: 50% 100%; animation: grow-up .55s var(--ease-out) both; }
@keyframes grow-up { from { transform: scaleY(0); } }

/* ---------- Settings window (dialog) ---------- */
.modal {
  opacity: 0; scale: .96; translate: 0 8px;
  transition: opacity var(--t-med) var(--ease-out), scale var(--t-med) var(--ease-out), translate var(--t-med) var(--ease-out),
    display var(--t-med) allow-discrete, overlay var(--t-med) allow-discrete;
}
.modal[open] { opacity: 1; scale: 1; translate: 0 0; }
@starting-style { .modal[open] { opacity: 0; scale: .96; translate: 0 8px; } }
.modal::backdrop {
  opacity: 0;
  transition: opacity var(--t-med) var(--ease-out), display var(--t-med) allow-discrete, overlay var(--t-med) allow-discrete;
}
.modal[open]::backdrop { opacity: 1; }
@starting-style { .modal[open]::backdrop { opacity: 0; } }

/* ---------- Live / Demo data badge (header) ----------
   Fades up when the page's first data arrives, the same way the tiles do */
#mode {
  transition: opacity var(--t-slow) var(--ease-out), translate var(--t-slow) var(--ease-out),
    color var(--t-med) ease, border-color var(--t-med) ease, background-color var(--t-med) ease;
}
@starting-style { #mode { opacity: 0; translate: 0 6px; } }

/* ---------- toast ---------- */
.toast { transition: opacity var(--t-med) var(--ease-out), transform var(--t-slow) var(--ease-spring); }

/* ---------- Van Tracker extras ---------- */
/* mileage chart bars grow when the chart's view changes (week / month / van) */
.mchart.grow .bar path { transform-box: fill-box; transform-origin: 50% 100%; animation: grow-up .5s var(--ease-out) both; }
.mchart.grow .bar:nth-child(odd) path { animation-delay: .03s; }
.mchart .bar path { transition: opacity var(--t-med) var(--ease-out), filter var(--t-med) var(--ease-out); }
.mchart .bar.hover path { filter: brightness(1.12); }

/* ---------- reduced motion: everything settles instantly ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after, *::backdrop {
    animation-duration: .01ms !important; animation-delay: 0s !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important; transition-delay: 0s !important; scroll-behavior: auto !important;
  }
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}
