/* ChangeGist motion system: loaded on every page, after style.css.

   One idea runs through it: "watch, spot, tell". Things settle like a page being read (soft rises), changes are
   marked like a highlighter (sweeps), and alerts arrive with a spring. Three intensities:
     high   the homepage hero and product demo (home.css)
     medium section reveals, cards, buttons, menus, page transitions (this file)
     low    forms, dashboards, settings: quick state feedback only, nothing that moves on its own.
   Everything here uses transform and opacity only, and "reduce motion" switches it all off (bottom of the file). */
:root {
  --m-fast: 140ms; --m-base: 260ms; --m-slow: 620ms; --m-cine: 900ms;
  --m-out: cubic-bezier(.2, .7, .2, 1);          /* settle: most entrances */
  --m-in-out: cubic-bezier(.65, 0, .35, 1);      /* sweeps and wipes */
  --m-spring: cubic-bezier(.34, 1.56, .64, 1);   /* presses, pops, arrivals */
  --m-glow: color-mix(in srgb, var(--accent) 40%, transparent);
}

/* ── page transitions: a short cross-fade between pages; the header stays put (Chromium; others just navigate) ── */
@view-transition { navigation: auto; }
.nav { view-transition-name: site-nav; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 180ms; animation-timing-function: var(--m-out); }

/* the header gains a shadow once you scroll (scroll-driven, no script) */
@supports (animation-timeline: scroll()) {
  .nav { animation: m-nav-lift linear both; animation-timeline: scroll(root); animation-range: 0 120px; }
  @keyframes m-nav-lift { to { box-shadow: 0 8px 28px -14px rgba(30, 10, 5, .45); } }
}

/* ── buttons: spring on press, a light sweep across the main ones on hover ── */
.btn { position: relative; overflow: hidden; isolation: isolate;
  transition: transform var(--m-fast) var(--m-spring), filter var(--m-fast), box-shadow var(--m-base) var(--m-out); }
.btn:hover { box-shadow: 0 2px 4px rgba(0,0,0,.1), 0 10px 26px -6px var(--m-glow); }
.btn:active { transform: translateY(0) scale(.965); transition-duration: 70ms; }
.btn:not(.btn-ghost):not(.btn-sm)::after { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: linear-gradient(105deg, transparent 35%, rgba(255,255,255,.28) 50%, transparent 65%);
  transform: translateX(-110%); }
.btn:not(.btn-ghost):not(.btn-sm):hover::after { transform: translateX(110%); transition: transform .7s var(--m-in-out); }
.btn:disabled, .btn[aria-busy="true"] { cursor: progress; }

/* links with an arrow nudge it */
a .icon:last-child, .link .icon:last-child { transition: transform var(--m-base) var(--m-spring); }
a:hover > .icon:last-child, a:focus-visible > .icon:last-child { transform: translateX(3px); }

/* keyboard focus draws in rather than snapping */
:focus-visible { outline-offset: 3px; transition: outline-offset var(--m-fast) var(--m-out); }

/* ── form fields: a soft glow grows on focus ── */
input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=hidden]), select, textarea {
  transition: border-color var(--m-fast), box-shadow var(--m-base) var(--m-out), background-color var(--m-fast); }
input:not([type=checkbox]):not([type=radio]):not([type=range]):focus, select:focus, textarea:focus {
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 22%, transparent); }

/* ── menus open with a quick drop from where you clicked ── */
.acct-menu[open] > .acct-pop, .row-menu[open] > .row-menu-pop { animation: m-drop var(--m-base) var(--m-spring) both;
  transform-origin: top right; }
@keyframes m-drop { from { opacity: 0; transform: translateY(-6px) scale(.96); } }
.acct-menu > summary { transition: transform var(--m-fast) var(--m-spring); }
.acct-menu > summary:active { transform: scale(.92); }

/* details panels (help, FAQs, settings) unfold */
details:not(.acct-menu):not(.row-menu)[open] > summary ~ * { animation: m-unfold var(--m-base) var(--m-out) both; }
@keyframes m-unfold { from { opacity: 0; transform: translateY(-4px); } }

/* ── scroll reveals, each with its own personality (motion.js adds .m-in; without script nothing is hidden) ──
   data-m="rise"   paragraphs and headings settle up
   data-m="wipe"   headings uncover left to right, like a highlighter
   data-m="deal"   cards arrive in turn with a slight turn, like being dealt
   data-m="slide"  list rows come in from the side
   data-m="zoom"   a product view comes forward
   data-m-stagger  on a parent: its [data-m] children follow one another */
.m-ready [data-m] { transition: opacity var(--m-slow) var(--m-out), transform var(--m-slow) var(--m-out), clip-path var(--m-cine) var(--m-in-out);
  transition-delay: calc(var(--m-i, 0) * 90ms); }
.m-ready [data-m="rise"]:not(.m-in) { opacity: 0; transform: translateY(22px); }
.m-ready [data-m="wipe"]:not(.m-in) { clip-path: inset(0 100% 0 0); }
.m-ready [data-m="wipe"] { clip-path: inset(0 -2% 0 0); }
.m-ready [data-m="deal"]:not(.m-in) { opacity: 0; transform: translateY(34px) rotate(var(--m-turn, -1.5deg)) scale(.97); }
.m-ready [data-m="deal"]:nth-child(2n) { --m-turn: 1.5deg; }
.m-ready [data-m="slide"]:not(.m-in) { opacity: 0; transform: translateX(-26px); }
.m-ready [data-m="zoom"]:not(.m-in) { opacity: 0; transform: perspective(1200px) translateY(40px) rotateX(10deg) scale(.95); }
.m-ready [data-m].m-in { transition-timing-function: var(--m-out), var(--m-spring), var(--m-in-out); }
.m-ready [data-m="deal"].m-in { transition-timing-function: var(--m-out), var(--m-spring); }

/* ── pointer light: cards with data-spot get a glow that follows the pointer (motion.js sets --sx/--sy) ── */
[data-spot] { position: relative; }
[data-spot]::before { content: ""; position: absolute; inset: -1px; border-radius: inherit; pointer-events: none; opacity: 0;
  background: radial-gradient(420px circle at var(--sx, 50%) var(--sy, 50%), color-mix(in srgb, var(--accent) 16%, transparent), transparent 60%);
  transition: opacity var(--m-base); }
[data-spot]::after { content: ""; position: absolute; inset: -1px; border-radius: inherit; pointer-events: none; opacity: 0; padding: 1px;
  background: radial-gradient(260px circle at var(--sx, 50%) var(--sy, 50%), var(--accent), transparent 70%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask-composite: exclude;
  transition: opacity var(--m-base); }
@media (hover: hover) and (pointer: fine) {
  [data-spot]:hover::before, [data-spot]:hover::after { opacity: 1; }
  [data-tilt] { transition: transform var(--m-slow) var(--m-out), box-shadow var(--m-base); transform-style: preserve-3d;
    transform: perspective(900px) rotateX(var(--ty, 0deg)) rotateY(var(--tx, 0deg)); }
  [data-tilt]:hover { transition-duration: var(--m-fast), var(--m-base); box-shadow: var(--shadow-lg); }
}

/* ── feedback: a tick that pops in on success, a dot that spins while something real is under way ── */
.m-pop { animation: m-pop .5s var(--m-spring) both; }
@keyframes m-pop { from { opacity: 0; transform: scale(.6); } }
.m-busy::before { content: ""; display: inline-block; width: .9em; height: .9em; margin-right: .45em; vertical-align: -.1em;
  border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: m-spin .7s linear infinite; }
@keyframes m-spin { to { transform: rotate(360deg); } }

/* ── the app (low tier): only real states move, and only briefly ──
   "Checking…" spins only while a check really is running (the server renders these only then); a page that changed
   this week glows once when the dashboard opens; problems never move, they just say so in words and colour. */
.notice-live::before, .dash .st-wait::before { content: ""; display: inline-block; width: .8em; height: .8em; margin-right: .5em;
  vertical-align: -.08em; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: m-spin .8s linear infinite; }
.dash .st-new { animation: m-glow-once 1.6s .6s var(--m-out) both; }
@keyframes m-glow-once { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, currentColor 45%, transparent); } 100% { box-shadow: 0 0 0 10px transparent; } }
.tag-new { animation: m-pop .5s .2s var(--m-spring) both; }
.pg-card[data-row] { transition: transform var(--m-base) var(--m-out), box-shadow var(--m-base), opacity var(--m-base); }

/* ── reduce motion: everything arrives finished, nothing moves on its own; colour and outline feedback stay ── */
@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
  .nav { animation: none; }
  .btn, .btn:active, .btn:hover { transform: none; }
  .btn::after { display: none; }
  a:hover > .icon:last-child, a:focus-visible > .icon:last-child { transform: none; }
  .acct-menu[open] > .acct-pop, .row-menu[open] > .row-menu-pop, details[open] > summary ~ * { animation: none; }
  .m-ready [data-m], .m-ready [data-m]:not(.m-in) { opacity: 1; transform: none; clip-path: none; transition: none; }
  [data-tilt] { transform: none !important; }
  .m-pop { animation: none; }
  .m-busy::before, .notice-live::before, .dash .st-wait::before { animation: none; border-right-color: currentColor; opacity: .5; }
  .dash .st-new, .tag-new { animation: none; }
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}
