/* ======================================================================================================================
   Motion: the Hub's one shared set of timings (Oct 21, 2026). Every screen loads this file, right after styles.css.
   Rules: Docs/Hub design standard.md (Motion, checks 26–32). Quick and subtle, only transform and opacity move, nothing
   ever waits for an animation, and with the phone's "reduce motion" on everything is a short plain fade or nothing.
   web/js/motion.js reads the same numbers (the sheets closing, a card growing into its sheet, the swipe back, the old
   screen fading out), so one change here changes the whole Hub.

   HOW TO CHANGE ANIMATION SPEED
   - Everything faster or slower: change --motion-speed below. 1 is normal; 0.8 is 20% faster; 1.25 is 25% slower;
     0 turns every animation off. Every duration and the list stagger follow it.
   - One kind only: change its number (--motion-fast, --motion-base, --motion-slow, --stagger-step, --stagger-max).
   - The feel of the movement (how it starts and settles): the --ease-* curves. Leave them unless something looks wrong.
   Then run `node tools/sw-files.mjs` and commit web/sw.js with it, so phones that have the Hub get the new file.
   ====================================================================================================================== */

:root {
  --motion-speed: 1;
  /* A press, an old screen fading out, a toast or fold going away. */
  --motion-fast: calc(120ms * var(--motion-speed));
  /* A new screen coming in, a toast, a sheet closing, a card on a list coming in. */
  --motion-base: calc(220ms * var(--motion-speed));
  /* A sheet opening, a card growing into its details. */
  --motion-slow: calc(280ms * var(--motion-speed));
  /* Cards on a list come in one after another, this far apart (Home, Today, the crew's Schedule)... */
  --stagger-step: calc(40ms * var(--motion-speed));
  /* ...but never later than this, so a long list doesn't drag: from the 7th card on they all come in together. */
  --stagger-max: calc(240ms * var(--motion-speed));
  /* The curves: a quick start that settles softly (most things); a gentle start and end; a sheet's glide. */
  --ease-out: cubic-bezier(.2, .8, .2, 1);
  --ease-in-out: cubic-bezier(.4, 0, .2, 1);
  --ease-sheet: cubic-bezier(.32, .72, 0, 1);
  /* The older names some area files still use. */
  --t-press: var(--motion-fast); --t-screen: var(--motion-base); --t-sheet: var(--motion-slow);
}

/* ---------- Screens flow in (motion.js enter) ---------- */
@keyframes cr-rise { from { opacity: 0; transform: translateY(8px); } }
@keyframes cr-item { from { opacity: 0; transform: translateY(6px); } }
@keyframes cr-push { from { opacity: 0; transform: translateX(28px); } }
@keyframes cr-pop { from { opacity: 0; transform: translateX(-28px); } }
@keyframes cr-fade { from { opacity: 0; } }
@keyframes cr-reveal { from { opacity: 0; transform: translateY(-4px); } }
.enter-rise { animation: cr-rise var(--motion-base) var(--ease-out) backwards; }
.enter-push { animation: cr-push var(--motion-base) var(--ease-out) backwards; }
.enter-pop { animation: cr-pop var(--motion-base) var(--ease-out) backwards; }
.enter-soft { animation: cr-fade var(--motion-base) ease-out backwards; }
.enter-swipe { animation: cr-fade var(--motion-fast) ease-out backwards; }
/* A screen that grows out of the row it was opened from (motion.js growIn): it grows from the row's top-left corner. */
.enter-grow { transform-origin: 0 0; }
/* The screen being left fades out over the new one as it rises in (motion.js enter). It is only a picture of the old
   screen: it takes no taps and screen readers skip it. Under the header and the bar. */
.screen-ghost { position: fixed; top: 0; z-index: 1; overflow: hidden; pointer-events: none; }
/* The same screen drawn again (the once-a-minute refresh, a save's answer): nothing moves or blinks (motion.js hush).
   The big title keeps its scroll animation, so it never flashes back while scrolled. */
.hush *:not([data-lt]), .hush *::before, .hush *::after { animation: none !important; transition: none !important; }

/* ---------- Cards on a list come in one after another, once their data is there ----------
   The screen marks each card .rt-enter with its place in the list (--i: 0, 1, 2...) and the list's box data-revealed
   when it draws the real data. Only in such a box: a card drawn anywhere else just shows. */
[data-revealed] .rt-enter { animation: cr-item var(--motion-base) var(--ease-out) backwards;
  animation-delay: min(calc(var(--i, 0) * var(--stagger-step)), var(--stagger-max)); }

/* ---------- A tap shows at once (a slight shrink for buttons and cards, a dim for rows) ---------- */
.btn, .ib, .help-q, .bn-add, .seg button, .chip, .sheet-x { transition: transform var(--motion-fast) var(--ease-out), opacity var(--motion-fast) ease-out; }
.btn:active, .ib:active, .help-q:active, .bn-add:active, .seg button:active, .chip:active, .sheet-x:active { transform: scale(.96); }
.li.tap, .si, .mi, .bnav button, summary, [data-press], [data-grow] { transition: opacity var(--motion-fast) ease-out; }
.li.tap:active, .si:active, .mi:active, .bnav button:active, summary:active, [data-press]:active, [data-grow]:active { opacity: .62; }
/* A card that is itself one button (an ad campaign, a tool, a photo tile): a smaller shrink, as a card is bigger. */
:is(a, button):is(.card, [class*="card"], [class*="tile"]) { transition: transform var(--motion-fast) var(--ease-out); }
:is(a, button):is(.card, [class*="card"], [class*="tile"]):active { transform: scale(.98); }

/* ---------- With a mouse: a button or card lifts a little under the pointer (never on a touch screen) ---------- */
@media (hover: hover) and (pointer: fine) {
  .ib:hover, .help-q:hover, .chip:hover, .bn-add:hover { transform: translateY(-1px); }
  :is(a, button):is(.card, [class*="card"], [class*="tile"]):hover { transform: translateY(-2px); }
  /* A press still shrinks while the pointer is over it (styles.css lifts a hovered .btn with a stronger rule). */
  .btn:not(.link):not([disabled]):active, .ib:active, .help-q:active, .chip:active, .bn-add:active { transform: scale(.96); }
  :is(a, button):is(.card, [class*="card"], [class*="tile"]):active { transform: scale(.98); }
}

/* ---------- Sheets slide up from the bottom on a phone, settle in on a computer ---------- */
.sheet-back { transition: opacity var(--motion-base) ease-out; }
.sheet-back.leaving { pointer-events: none; }
@media (max-width: 719px) {
  .sheet { transform: translateY(100%); transition: transform var(--motion-slow) var(--ease-sheet); }
  .sheet-back.open .sheet { transform: none; }
  /* The ☰ menu too: from the bottom, as every other sheet (it was a drawer from the left). */
  .sheet-back.nav-back { align-items: flex-end; justify-content: stretch; }
  .nav-back .sheet.nav-sheet { width: 100%; max-width: none; height: auto; max-height: calc(90 * var(--vh)); border-right: 0; border-radius: 28px 28px 0 0;
    background: var(--surface); box-shadow: var(--sh-sheet); transform: translateY(100%); padding-bottom: calc(16px + var(--safe-b)); }
  .nav-back.open .sheet.nav-sheet { transform: none; }
}
@media (min-width: 720px) {
  .sheet { opacity: 0; transform: translateY(10px) scale(.98); transition: transform var(--motion-base) var(--ease-out), opacity var(--motion-base) ease-out; }
  .sheet-back.open .sheet { opacity: 1; transform: none; }
}
/* A sheet opened from a card grows out of it (motion.js growIn, a transform and a fade): no slide of its own. A sheet being
   pulled down follows the finger with no easing; its top is the handle. */
.sheet-back.grow .sheet, .sheet-back.grow.open .sheet { transform: none; opacity: 1; transition: none; transform-origin: 0 0; }
.sheet.dragging { transition: none; }
.sheet-head.drag-h { touch-action: none; }
@media (min-width: 720px) { .sheet-head.drag-h { touch-action: auto; } }

/* ---------- Toasts rise in, and go a little faster than they came ---------- */
.toast { transition: opacity var(--motion-fast) ease-out, transform var(--motion-fast) var(--ease-out), visibility 0s linear var(--motion-fast); }
.toast.show { transition: opacity var(--motion-base) ease-out, transform var(--motion-base) var(--ease-out), visibility 0s; }

/* ---------- Folds fade open (closing: motion.js foldMotion); names on icon buttons; the header's slim title ---------- */
details[open] > :not(summary) { animation: cr-reveal var(--motion-base) var(--ease-out) backwards; }
[data-tip]::after { transition: opacity var(--motion-fast) ease-out, transform var(--motion-fast) ease-out; }
body.has-lt .ah-title { transition: opacity var(--motion-base) var(--ease-out), transform var(--motion-base) var(--ease-out); }

/* ---------- Reduce motion (the phone's setting): plain short fades, nothing moves ---------- */
@media (prefers-reduced-motion: reduce) {
  :root { --stagger-step: 0ms; }
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; animation-delay: 0s !important;
    transition-duration: .01ms !important; transition-delay: 0s !important; scroll-behavior: auto !important; }
  .enter-rise, .enter-push, .enter-pop, .enter-soft, .enter-swipe { animation: cr-fade var(--motion-fast) ease-out backwards !important; }
  [data-revealed] .rt-enter { animation: cr-fade var(--motion-fast) ease-out backwards !important; }
  .sheet-back { transition: opacity var(--motion-fast) ease-out !important; }
  .sheet, .sheet-back.open .sheet, .nav-back .sheet.nav-sheet { transform: none !important; }
  .toast, .toast.show { transform: translate(-50%, 0); }
  .toast { transition: opacity var(--motion-fast) ease-out, visibility 0s linear var(--motion-fast) !important; }
  .toast.show { transition: opacity var(--motion-fast) ease-out, visibility 0s !important; }
  .btn:active, .ib:active, .help-q:active, .bn-add:active, .seg button:active, .chip:active, .sheet-x:active,
  .btn:not(.link):not([disabled]):hover, .ib:hover, .help-q:hover, .chip:hover, .bn-add:hover,
  :is(a, button):is(.card, [class*="card"], [class*="tile"]):is(:hover, :active) { transform: none !important; }
  details[open] > :not(summary) { animation: cr-fade var(--motion-fast) ease-out backwards !important; }
  .sk::after { display: none; }
  .st h1[data-lt] { animation: none !important; }
}

/* The design's pieces and frame (styles.css, "design primitives" and "the frame"): no page rise or drawer slide. */
@media (prefers-reduced-motion: reduce) {
  .ds-page, .ds-inbox-page { animation: none; }
  .ds-sidebar, .ds-sidebar-nav button, .ds-button { transition: none; }
}
