/* Motion, shared by every portal (docs/adr/0211): the loading bar along the
 * top of the window, the small burst for good news and the page cross-fade.
 * leaves.js (beside this file) drives the bar and the burst; this file draws
 * them. Decoration only: everything is aria-hidden or a transition, and
 * reduced motion turns it off.
 *
 * Each app keeps its own particle. This file draws a LEAF by default, which
 * the Intranet (green) and uTrust (autumn) use as they are; an app with
 * another particle (Tools' coins and notes, PMC's sparkles) redraws `.leaf`
 * and its `--s0..2` shapes in its own stylesheet, which loads after this one.
 * The class names stay `leaf*`: they are leaves.js's, and Cadence keeps a
 * copy of that script.
 *
 * Tokens an app sets (defaults are the Intranet's green):
 *   --motion-c0 … --motion-c4   the five particle colours, light to dark
 *   --motion-bar                the loading bar's gradient
 */
:root {
  --motion-c0: #b7dc8f;
  --motion-c1: #7cc28a;
  --motion-c2: #3f9a6b;
  --motion-c3: #2e8159;
  --motion-c4: #1f5c40;
  --motion-bar: linear-gradient(90deg, #b7dc8f, #3f9a6b 35%, #1f5c40 65%, #b7dc8f);
}

/* One particle: by default the two-corner leaf with a midrib, in three
   proportions and five colours. leaves.js sets the per-particle custom
   properties. */
.leaf {
  position: absolute; display: block; width: 11px; height: 11px;
  border-radius: 0 100% 0 100%; background: var(--leaf-c, var(--motion-c2));
  box-shadow: inset -1px -1px 0 rgba(0,0,0,.08); pointer-events: none; will-change: transform, opacity;
}
.leaf::after {
  content: ""; position: absolute; left: 50%; top: 50%; width: 130%; height: 1.2px;
  background: rgba(255,255,255,.55); transform: translate(-50%, -50%) rotate(-45deg);
}
.leaf--s1 { width: 8px; height: 13px; border-radius: 0 100% 0 100% / 0 70% 0 70%; }
.leaf--s2 { width: 14px; height: 9px; }
.leaf--c0 { --leaf-c: var(--motion-c0); }
.leaf--c1 { --leaf-c: var(--motion-c1); }
.leaf--c2 { --leaf-c: var(--motion-c2); }
.leaf--c3 { --leaf-c: var(--motion-c3); }
.leaf--c4 { --leaf-c: var(--motion-c4); }

/* The loading bar: a gradient sweep along the top edge, particles drifting
   off it while the page is on its way (after 180ms, so quick loads never
   flash it). */
.leafbar { position: fixed; inset: 0 0 auto 0; height: 0; z-index: 400; pointer-events: none; opacity: 0; transition: opacity .2s ease; }
.leafbar--on { opacity: 1; }
.leafbar--done { opacity: 0; transition: opacity .4s ease .05s; }
.leafbar__track {
  position: absolute; left: 0; top: 0; height: 3px; width: 100%; border-radius: 0 3px 3px 0;
  background: var(--motion-bar); background-size: 200% 100%;
  transform-origin: 0 50%; transform: scaleX(.08);
  animation: leafbar-grow 2.4s cubic-bezier(.1,.7,.3,1) forwards, leafbar-sheen 1.6s linear infinite;
}
.leafbar--done .leafbar__track { animation: leafbar-sheen 1.6s linear infinite; transform: scaleX(1); transition: transform .25s ease; }
.leafbar__leaf { left: var(--x); top: -2px; opacity: 0; animation: leafbar-leaf 2.2s ease-in var(--delay) infinite; }
@keyframes leafbar-grow { to { transform: scaleX(.85); } }
@keyframes leafbar-sheen { to { background-position: -200% 0; } }
@keyframes leafbar-leaf {
  0% { opacity: 0; transform: translate(0, 0) rotate(0); }
  12% { opacity: .95; }
  50% { transform: translate(calc(var(--drift) * -.5), 34px) rotate(calc(var(--spin) * .5)); }
  85% { opacity: .8; }
  100% { opacity: 0; transform: translate(var(--drift), 70px) rotate(var(--spin)); }
}

/* The burst: particles tossed up from an element and falling away. Good news
   only (a saved receipt, "all caught up"), never an error. */
.leafburst { position: fixed; top: var(--top); left: var(--left); width: var(--width); height: 0; z-index: 400; pointer-events: none; }
.leafburst__leaf { left: var(--x); top: 0; opacity: 0; animation: leafburst-fall var(--dur) cubic-bezier(.25,.6,.4,1) var(--delay) forwards; }
@keyframes leafburst-fall {
  0% { opacity: 0; transform: translate(0, 0) rotate(0) scale(.6); }
  12% { opacity: 1; transform: translate(calc(var(--drift) * .2), calc(var(--rise) * -1)) rotate(calc(var(--spin) * .2)) scale(1); }
  45% { transform: translate(calc(var(--drift) * -.35), calc(var(--fall) * .35)) rotate(calc(var(--spin) * .55)); }
  75% { opacity: .9; transform: translate(calc(var(--drift) * .6), calc(var(--fall) * .7)) rotate(calc(var(--spin) * .8)); }
  100% { opacity: 0; transform: translate(var(--drift), var(--fall)) rotate(var(--spin)); }
}

/* Pages cross-fade; the sidebar holds still (browsers without view
   transitions simply navigate). An app whose content area is not `.main`
   names its own (PMC: `.wrap`). Swapped-in htmx content settles in with
   vt-in too, but that rule (`.htmx-added`) stays LAST in each app's own
   stylesheet: it outranks a row's own flash there, and moving it here would
   change that. */
@view-transition { navigation: auto; }
.sidebar { view-transition-name: sidebar; }
.main { view-transition-name: main; }
::view-transition-old(main) { animation: vt-out .12s ease-in both; }
::view-transition-new(main) { animation: vt-in .22s cubic-bezier(.2,.7,.3,1) both; }
@keyframes vt-out { to { opacity: 0; } }
@keyframes vt-in { from { opacity: 0; transform: translateY(6px); } }

@media (prefers-reduced-motion: reduce) {
  .leafbar__leaf, .leafburst { display: none; }
  .leafbar__track { animation: none; transform: scaleX(.85); }
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}
