/* Motion and feedback (#3443, design epic #3432): motion tokens, the org
 * loader, the running indicator, the success celebration, and the empty and
 * error shells. Helpers in feedback.ts. Keyframes are exact from the Nov-4
 * Figma (get_motion_context); what Figma does not draw is marked "proposed,
 * not in Figma". Loaders loop while they wait; the celebration plays once and
 * rests on its final frame (Figma loops it; proposed). Every animation has a
 * reduced-motion fallback, written twice: under the media query, and under
 * :root[data-motion="reduce"] so the gallery can show it without emulation. */

:root {
  /* ---- Motion tokens ---- */
  --motion-instant: 80ms;
  --motion-fast: 120ms;
  --motion-base: 150ms;      /* chevrons, switches */
  --motion-slow: 200ms;      /* crossfades: Figma's phase fades, 2.5% of 8 s */
  --motion-celebrate: 2200ms;
  --motion-pulse: 2000ms;
  --motion-loader: 8000ms;
  --motion-unplug: 3200ms;   /* the unplugged illustration (1:13443) */
  /* The app's loaders and toasts that Figma does not draw keep their timing
     (proposed, not in Figma). */
  --motion-toast: 250ms;
  --motion-spin: 800ms;      /* inline spinner */
  --motion-spin-slow: 1000ms; /* ms-spin */
  --motion-spinner: 1600ms;  /* page spinner (morph) */
  --motion-float: 2400ms;    /* balance spent / credited */
  --motion-float-long: 2800ms;
  --ease-standard: ease-in-out;          /* every Figma loader and pulse track */
  --ease-out: ease-out;                  /* Figma celebration entries */
  --ease-emphasis: cubic-bezier(.2, .7, .2, 1);
  --ease-out-expo: cubic-bezier(.22, 1, .36, 1); /* Figma's "Funds added" wallet (#3470) */

  /* ---- Colors only these components use ---- */
  --loader-text: #8cbaa6;    /* org loader phase line, on the dark card */
  /* Running indicator: Figma's mint is 1.9:1 on white, below the 3:1 a
     graphic needs, so light mode uses the nearest passing green. */
  --running-ink: var(--brand-text);
  --celebrate-halo: #f3fcf7;
  --celebrate-soft: #83d8b5;
  --celebrate-ring: #b8edd2;
  --celebrate-spark: #a6dfc4;
  --celebrate-fill: #ffffff;
  /* The success motif card is dark in both themes (a terminal). Figma's
     label grey #6e7681 is 4.1:1 at 8px there; #7d8590 is the nearest AA. */
  --motif-label: #7d8590;
  --motif-fg: #c9d1d9;
  --motif-line: #238636;
  --motif-check: #3fb950;
  /* Unplugged illustration (1:13443): Figma's eight mints mapped to the
     nearest tokens, so dark (not in Figma) follows the theme. */
  --plug-ink: var(--brand-text);
  --plug-cord-from: var(--celebrate-soft);
  --plug-cord-to: var(--progress-to);
}
/* Dark values (proposed, not in Figma: the celebration is drawn light only). */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --running-ink: var(--brand-mint); --celebrate-halo: color-mix(in srgb, var(--brand) 12%, var(--surface)); --celebrate-fill: var(--surface); }
}
:root[data-theme="dark"] { --running-ink: var(--brand-mint); --celebrate-halo: color-mix(in srgb, var(--brand) 12%, var(--surface)); --celebrate-fill: var(--surface); }

/* ---- Org loader (18:4839): the card in the sidebar's org slot, dark in
   both themes. data-phase loading | done | error; finished steps light
   their share of the 12 cells (.on). data-mode="timeline" plays Figma's 8 s
   demo instead (the gallery's comparison; the product follows real reads). */
.ms-org-loader {
  --ms-cell-idle: color-mix(in srgb, var(--loader-cell) 12%, transparent);
  --ms-cell-lit: color-mix(in srgb, var(--loader-cell) 55%, transparent);
  --ms-cell-done: color-mix(in srgb, var(--loader-cell) 85%, transparent);
  position: relative; box-sizing: border-box; width: 189px; min-height: 68px; padding: 9px 11px;
  border: 1px solid color-mix(in srgb, var(--brand) 20%, transparent); border-radius: var(--radius-xl);
  background: color-mix(in srgb, var(--brand) 10%, var(--sidebar-bg)); color: var(--sidebar-fg);
}
.ms-org-loader-head { display: flex; align-items: center; gap: var(--space-3); }
.ms-org-loader-head .avatar { width: 28px; height: 28px; flex: none; border-radius: var(--radius); font: var(--type-label); font-size: 10px; }
.ms-org-loader-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: 700 12px/16px var(--font-sans); }
.ms-org-loader-grid { display: grid; grid-template-columns: repeat(4, 3px); gap: 2px; margin-right: 1px; }
.ms-org-loader-grid i { width: 3px; height: 3px; border-radius: 0.6px; background: var(--ms-cell-idle); animation: none var(--motion-loader) var(--ease-standard) infinite; }
.ms-org-loader-line { display: flex; justify-content: space-between; gap: var(--space-2); margin-top: 6px; font: 600 9px/13.5px var(--font-sans); color: var(--loader-text); white-space: nowrap; }
.ms-org-loader-retry { margin-top: var(--space-1); padding: 0; border: 0; background: none; font: 600 9px/13.5px var(--font-sans); color: var(--brand-mint); text-decoration: underline; cursor: pointer; }
/* Per-cell order of Figma's sweep: its flash start, % of the 8 s timeline. */
.ms-org-loader-grid i:nth-child(1) { --at: 3.125; } .ms-org-loader-grid i:nth-child(2) { --at: 24.375; } .ms-org-loader-grid i:nth-child(3) { --at: 39.375; } .ms-org-loader-grid i:nth-child(4) { --at: 61.875; }
.ms-org-loader-grid i:nth-child(5) { --at: 9.375; } .ms-org-loader-grid i:nth-child(6) { --at: 29.375; } .ms-org-loader-grid i:nth-child(7) { --at: 45.625; } .ms-org-loader-grid i:nth-child(8) { --at: 66.875; }
.ms-org-loader-grid i:nth-child(9) { --at: 15.625; } .ms-org-loader-grid i:nth-child(10) { --at: 34.375; } .ms-org-loader-grid i:nth-child(11) { --at: 51.875; } .ms-org-loader-grid i:nth-child(12) { --at: 71.875; }

/* Product: a finished step's cells flash once (150 ms) and settle at .55
   (250 ms), Figma's per-cell segment; cells still waiting run the sweep in
   Figma's order on a 2 s loop (proposed, not in Figma); Completed flashes
   every cell (200 ms) and holds .85 (300 ms), Figma's 78.75-85%. */
.ms-org-loader-grid i.on { background: var(--ms-cell-lit); animation: ms-loader-cell-on calc(var(--motion-base) + 250ms) var(--ease-standard) both; }
.ms-org-loader[data-phase="loading"] .ms-org-loader-grid i:not(.on) { animation: ms-loader-cell-wait var(--motion-pulse) var(--ease-standard) calc(var(--at) * 20ms) infinite; }
.ms-org-loader[data-phase="done"] .ms-org-loader-grid i { background: var(--ms-cell-done); animation: ms-loader-cell-all calc(var(--motion-slow) + 300ms) var(--ease-standard) both; }
.ms-org-loader[data-phase="error"] .ms-org-loader-line { color: var(--alert-dot); }
.ms-org-loader-text, .ms-org-loader-step { animation: ms-fade-in var(--motion-slow) var(--ease-standard); }
@keyframes ms-loader-cell-on { 0% { background: var(--ms-cell-idle); } 37.5% { background: var(--loader-cell); } 100% { background: var(--ms-cell-lit); } }
@keyframes ms-loader-cell-wait { 0%, 30% { background: var(--ms-cell-idle); } 37.5% { background: var(--loader-cell); } 50%, 100% { background: var(--ms-cell-idle); } }
@keyframes ms-loader-cell-all { 0% { background: var(--ms-cell-lit); } 40% { background: var(--loader-cell); } 100% { background: var(--ms-cell-done); } }
@keyframes ms-fade-in { from { opacity: 0; } to { opacity: 1; } }

/* ---- Page loader (#4179): the org loader's card, centered in the content
   area while #content holds a loader() marker (api.ts) -- the one loading
   state for anything not ready to show. The page waits hidden and the card
   fades in only after --page-loader-delay, so a fast load never flashes it. Below
   the top bar and the sidebar (left of it on desktop, none on phones or the
   focused screen); it never takes a click. */
:root { --page-loader-delay: 150ms; }
.page-loader { display: none; }
.content:has([data-loading]) + .page-loader {
  display: grid; place-items: center; position: fixed; inset: var(--topbar-height) 0 0 var(--sidebar-width); z-index: 1; pointer-events: none;
  animation: ms-fade-in var(--motion-slow) var(--ease-standard) var(--page-loader-delay) both;
}
.content:has([data-loading]) > * { visibility: hidden; }
/* The marker itself stays visible (it draws nothing: only its visually hidden label), so its
   role="status" stays in the accessibility tree and the wait is announced while the page is hidden. */
.content:has([data-loading]) [data-loading] { visibility: visible; }
.page-loader .ms-org-loader { min-height: 0; transform: scale(1.25); }
.inline-loading { color: var(--fg-muted); }
@media (max-width: 860px) { .content:has([data-loading]) + .page-loader { left: 0; } }
.shell[data-focused] .content:has([data-loading]) + .page-loader { inset: 0; }

/* Timeline (Figma 8 s, looping): per-cell tracks and the four phase lines. */
.ms-org-loader[data-mode="timeline"] .ms-org-loader-phases { display: grid; margin-top: 6px; }
.ms-org-loader[data-mode="timeline"] .ms-org-loader-phases > .ms-org-loader-line { grid-area: 1 / 1; margin: 0; opacity: 0; animation: none var(--motion-loader) linear infinite; }
.ms-org-loader[data-mode="timeline"] .ms-org-loader-phases > :nth-child(1) { animation-name: ms-loader-phase-1; }
.ms-org-loader[data-mode="timeline"] .ms-org-loader-phases > :nth-child(2) { animation-name: ms-loader-phase-2; }
.ms-org-loader[data-mode="timeline"] .ms-org-loader-phases > :nth-child(3) { animation-name: ms-loader-phase-3; }
.ms-org-loader[data-mode="timeline"] .ms-org-loader-phases > :nth-child(4) { animation-name: ms-loader-phase-4; }
@keyframes ms-loader-phase-1 { 0%, 22.5% { opacity: 1; animation-timing-function: ease-in-out; } 25%, 100% { opacity: 0; } }
@keyframes ms-loader-phase-2 { 0%, 22.5% { opacity: 0; animation-timing-function: ease-in-out; } 25%, 60% { opacity: 1; animation-timing-function: ease-in-out; } 62.5%, 100% { opacity: 0; } }
@keyframes ms-loader-phase-3 { 0%, 60% { opacity: 0; animation-timing-function: ease-in-out; } 62.5%, 76.25% { opacity: 1; animation-timing-function: ease-in-out; } 78.75%, 100% { opacity: 0; } }
@keyframes ms-loader-phase-4 { 0%, 76.25% { opacity: 0; animation-timing-function: ease-in-out; } 78.75%, 100% { opacity: 1; } }
@keyframes ms-loader-cell-1 { 0%, 3.125% { background: var(--ms-cell-idle); } 5% { background: var(--loader-cell); } 8.125%, 78.75% { background: var(--ms-cell-lit); } 81.25% { background: var(--loader-cell); } 85%, 100% { background: var(--ms-cell-done); } }
@keyframes ms-loader-cell-2 { 0%, 24.375% { background: var(--ms-cell-idle); } 26.25% { background: var(--loader-cell); } 29.375%, 78.75% { background: var(--ms-cell-lit); } 81.25% { background: var(--loader-cell); } 85%, 100% { background: var(--ms-cell-done); } }
@keyframes ms-loader-cell-3 { 0%, 39.375% { background: var(--ms-cell-idle); } 41.25% { background: var(--loader-cell); } 44.375%, 78.75% { background: var(--ms-cell-lit); } 81.25% { background: var(--loader-cell); } 85%, 100% { background: var(--ms-cell-done); } }
@keyframes ms-loader-cell-4 { 0%, 61.875% { background: var(--ms-cell-idle); } 63.75% { background: var(--loader-cell); } 66.875%, 78.75% { background: var(--ms-cell-lit); } 81.25% { background: var(--loader-cell); } 85%, 100% { background: var(--ms-cell-done); } }
@keyframes ms-loader-cell-5 { 0%, 9.375% { background: var(--ms-cell-idle); } 11.25% { background: var(--loader-cell); } 14.375%, 78.75% { background: var(--ms-cell-lit); } 81.25% { background: var(--loader-cell); } 85%, 100% { background: var(--ms-cell-done); } }
@keyframes ms-loader-cell-6 { 0%, 29.375% { background: var(--ms-cell-idle); } 31.25% { background: var(--loader-cell); } 34.375%, 78.75% { background: var(--ms-cell-lit); } 81.25% { background: var(--loader-cell); } 85%, 100% { background: var(--ms-cell-done); } }
@keyframes ms-loader-cell-7 { 0%, 45.625% { background: var(--ms-cell-idle); } 47.5% { background: var(--loader-cell); } 50.625%, 78.75% { background: var(--ms-cell-lit); } 81.25% { background: var(--loader-cell); } 85%, 100% { background: var(--ms-cell-done); } }
@keyframes ms-loader-cell-8 { 0%, 66.875% { background: var(--ms-cell-idle); } 68.75% { background: var(--loader-cell); } 71.875%, 78.75% { background: var(--ms-cell-lit); } 81.25% { background: var(--loader-cell); } 85%, 100% { background: var(--ms-cell-done); } }
@keyframes ms-loader-cell-9 { 0%, 15.625% { background: var(--ms-cell-idle); } 17.5% { background: var(--loader-cell); } 20.625%, 78.75% { background: var(--ms-cell-lit); } 81.25% { background: var(--loader-cell); } 85%, 100% { background: var(--ms-cell-done); } }
@keyframes ms-loader-cell-10 { 0%, 34.375% { background: var(--ms-cell-idle); } 36.25% { background: var(--loader-cell); } 39.375%, 78.75% { background: var(--ms-cell-lit); } 81.25% { background: var(--loader-cell); } 85%, 100% { background: var(--ms-cell-done); } }
@keyframes ms-loader-cell-11 { 0%, 51.875% { background: var(--ms-cell-idle); } 53.75% { background: var(--loader-cell); } 56.875%, 78.75% { background: var(--ms-cell-lit); } 81.25% { background: var(--loader-cell); } 85%, 100% { background: var(--ms-cell-done); } }
@keyframes ms-loader-cell-12 { 0%, 71.875% { background: var(--ms-cell-idle); } 73.75% { background: var(--loader-cell); } 76.875%, 78.75% { background: var(--ms-cell-lit); } 81.25% { background: var(--loader-cell); } 85%, 100% { background: var(--ms-cell-done); } }
.ms-org-loader[data-mode="timeline"] i:nth-child(1) { animation-name: ms-loader-cell-1; } .ms-org-loader[data-mode="timeline"] i:nth-child(2) { animation-name: ms-loader-cell-2; } .ms-org-loader[data-mode="timeline"] i:nth-child(3) { animation-name: ms-loader-cell-3; }
.ms-org-loader[data-mode="timeline"] i:nth-child(4) { animation-name: ms-loader-cell-4; } .ms-org-loader[data-mode="timeline"] i:nth-child(5) { animation-name: ms-loader-cell-5; } .ms-org-loader[data-mode="timeline"] i:nth-child(6) { animation-name: ms-loader-cell-6; }
.ms-org-loader[data-mode="timeline"] i:nth-child(7) { animation-name: ms-loader-cell-7; } .ms-org-loader[data-mode="timeline"] i:nth-child(8) { animation-name: ms-loader-cell-8; } .ms-org-loader[data-mode="timeline"] i:nth-child(9) { animation-name: ms-loader-cell-9; }
.ms-org-loader[data-mode="timeline"] i:nth-child(10) { animation-name: ms-loader-cell-10; } .ms-org-loader[data-mode="timeline"] i:nth-child(11) { animation-name: ms-loader-cell-11; } .ms-org-loader[data-mode="timeline"] i:nth-child(12) { animation-name: ms-loader-cell-12; }

/* ---- Running indicator (25:40517, 2 s loop): a 35 px box, the code glyph
   breathing over three staggered dots. */
.ms-running { position: relative; display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; width: 35px; height: 35px; flex: none; border: 1px solid var(--border-control); border-radius: var(--radius); background: var(--surface); color: var(--running-ink); }
.ms-running-dots { display: flex; gap: 2px; }
.ms-running-dots i { width: 6px; height: 6px; border-radius: 50%; background: currentColor; animation: none var(--motion-pulse) var(--ease-standard) infinite; }
.ms-running-dots i:nth-child(1) { animation-name: ms-running-dot-1; }
.ms-running-dots i:nth-child(2) { animation-name: ms-running-dot-2; }
.ms-running-dots i:nth-child(3) { animation-name: ms-running-dot-3; }
.ms-running-code { position: absolute; left: 50%; top: 50%; width: 14px; height: 14px; margin: -6.5px 0 0 -6.5px; stroke-width: 3.43; /* Figma: 2 px at 14 px */ animation: ms-running-code var(--motion-pulse) var(--ease-standard) infinite; }
@keyframes ms-running-code { 0%, 50%, 100% { opacity: .7; } 25%, 75% { opacity: 1; } }
@keyframes ms-running-dot-1 { 0%, 50%, 100% { opacity: 1; } 6.25%, 43.75%, 56.25%, 93.75% { opacity: .783; } 12.5%, 37.5%, 62.5%, 87.5% { opacity: .4; } 18.75%, 31.25%, 68.75%, 81.25% { opacity: .217; } 25%, 75% { opacity: .2; } }
@keyframes ms-running-dot-2 { 0%, 50%, 100% { opacity: .25; } 6.25%, 56.25% { opacity: .517; } 12.5%, 62.5% { opacity: .896; } 18.75%, 68.75% { opacity: .973; } 25%, 75% { opacity: .65; } 31.25%, 81.25% { opacity: .31; } 37.5%, 87.5% { opacity: .204; } 43.75%, 93.75% { opacity: .2; } }
@keyframes ms-running-dot-3 { 0%, 50%, 100% { opacity: .25; } 6.25%, 56.25% { opacity: .2; } 12.5%, 62.5% { opacity: .204; } 18.75%, 68.75% { opacity: .31; } 25%, 75% { opacity: .65; } 31.25%, 81.25% { opacity: .973; } 37.5%, 87.5% { opacity: .896; } 43.75%, 93.75% { opacity: .517; } }

/* ---- Success celebration (1:10154, 2.2 s): plays once and rests on its
   final frame, which is also each element's static style (the reduced-motion
   frame). Times are % of the 2.2 s Figma timeline. */
.ms-success { display: block; width: 172px; height: 78px; overflow: visible; }
.ms-success * { transform-box: fill-box; transform-origin: center; animation-duration: var(--motion-celebrate); animation-fill-mode: both; animation-timing-function: var(--ease-out); }
.ms-success-halo { fill: var(--celebrate-halo); scale: 1.035; animation-name: ms-success-halo, ms-success-halo-in; animation-timing-function: linear; }
.ms-success-stream { fill: none; stroke-width: 5; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1 1; animation-name: ms-success-draw; }
.ms-success-stream-1 { stroke: var(--brand); animation-timing-function: var(--ease-standard); }
.ms-success-stream-2 { stroke: var(--celebrate-soft); animation-name: ms-success-draw-2; animation-timing-function: linear; }
.ms-success-unified { stroke: url(#ms-success-unified); animation-name: ms-success-draw-3; animation-timing-function: linear; }
.ms-success-source { fill: var(--celebrate-fill); stroke-width: 2; opacity: .7; animation-name: ms-success-source; }
.ms-success-source-1 { stroke: var(--brand); }
.ms-success-source-2 { stroke: var(--celebrate-soft); }
.ms-success-junction { fill: var(--brand); animation-name: ms-success-junction; animation-timing-function: linear; }
.ms-success-badge { fill: var(--celebrate-fill); stroke: var(--celebrate-ring); stroke-width: 4; animation-name: ms-success-badge; animation-timing-function: linear; }
.ms-success-check { fill: none; stroke: var(--brand-text); stroke-width: 3.5; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1 1; animation-name: ms-success-check; animation-timing-function: linear; }
.ms-success-ripple { fill: none; stroke: var(--celebrate-soft); opacity: 0; scale: 1.85; animation-name: ms-success-ripple; animation-timing-function: linear; }
/* Sparks: six "+" that start at an offset (--dx, --dy) and turned 22 deg,
   then pop (scale .4 -> 1.12 -> 1) into place, 45 ms apart from 51.4%; the
   last stretch drifts a few px further (--ex, --ey) and fades to .75. */
.ms-success-spark { fill: none; stroke-width: 1.6; stroke-linecap: round; opacity: .75; translate: var(--ex) var(--ey);
  --at: calc(1130ms + var(--i) * 45ms); --tail: calc(470ms - var(--i) * 45ms);
  animation: ms-spark-pop 600ms var(--ease-out) var(--at) both, ms-spark-turn 700ms var(--ease-out) var(--at) both,
    ms-spark-move 600ms var(--ease-out) var(--at) both, ms-spark-drift var(--tail) var(--ease-standard) calc(var(--at) + 600ms) forwards,
    ms-spark-in 120ms var(--ease-out) var(--at) both, ms-spark-settle var(--tail) var(--ease-out) calc(var(--at) + 600ms) forwards; }
.ms-success-spark-brand { stroke: var(--brand); }
.ms-success-spark-soft { stroke: var(--celebrate-soft); }
.ms-success-spark-pale { stroke: var(--celebrate-spark); }
.ms-success-spark-ring { stroke: var(--celebrate-ring); }
@keyframes ms-success-halo { 0%, 37.273% { scale: .8; animation-timing-function: ease-out; } 68.182% { scale: 1; animation-timing-function: ease-in-out; } 100% { scale: 1.035; } }
@keyframes ms-success-halo-in { 0%, 37.273% { opacity: 0; animation-timing-function: ease-out; } 63.636%, 100% { opacity: 1; } }
@keyframes ms-success-draw { 0% { stroke-dasharray: 0 1; visibility: hidden; } 31.818%, 100% { stroke-dasharray: 1 1; visibility: visible; } }
@keyframes ms-success-draw-2 { 0%, 4.091% { stroke-dasharray: 0 1; visibility: hidden; animation-timing-function: ease-in-out; } 35%, 100% { stroke-dasharray: 1 1; visibility: visible; } }
@keyframes ms-success-draw-3 { 0%, 29.091% { stroke-dasharray: 0 1; visibility: hidden; animation-timing-function: ease-out; } 42.727%, 100% { stroke-dasharray: 1 1; visibility: visible; } }
@keyframes ms-success-source { 0% { opacity: .35; } 9.091% { opacity: 1; } 36.364%, 100% { opacity: .7; } }
@keyframes ms-success-junction { 0%, 27.727% { scale: .4; opacity: 0; animation-timing-function: ease-out; } 35.455% { opacity: 1; } 38.182% { scale: 1.18; animation-timing-function: ease-out; } 46.818%, 100% { scale: 1; opacity: 1; } }
@keyframes ms-success-badge { 0%, 36.818% { scale: .78; opacity: 0; animation-timing-function: ease-out; } 44.545% { opacity: 1; } 49.091% { scale: 1.05; animation-timing-function: ease-out; } 59.091%, 100% { scale: 1; opacity: 1; } }
@keyframes ms-success-check { 0%, 46.364% { stroke-dasharray: 0 1; visibility: hidden; animation-timing-function: ease-in-out; } 61.818%, 100% { stroke-dasharray: 1 1; visibility: visible; } }
@keyframes ms-success-ripple { 0%, 50.909% { scale: 1; opacity: 0; animation-timing-function: ease-out; } 54.545% { opacity: .55; animation-timing-function: ease-out; } 88.636%, 100% { scale: 1.85; opacity: 0; } }
@keyframes ms-spark-pop { 0% { scale: .4; } 50% { scale: 1.12; } 100% { scale: 1; } }
@keyframes ms-spark-turn { from { rotate: var(--r); } to { rotate: 0deg; } }
@keyframes ms-spark-move { from { translate: var(--dx) var(--dy); } to { translate: 0 0; } }
@keyframes ms-spark-drift { from { translate: 0 0; } to { translate: var(--ex) var(--ey); } }
@keyframes ms-spark-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes ms-spark-settle { from { opacity: 1; } to { opacity: .75; } }

/* The motif card under the illustration: org -> repository -> MergeSafe
   light up in turn (dots and lines .22 -> 1, checks draw). */
.ms-motif { display: grid; gap: 10px; padding: var(--space-4); border-radius: var(--radius-xl); background: var(--ink); font-family: var(--font-mono); }
.ms-motif-node { display: flex; align-items: center; gap: 10px; }
.ms-motif-dot { width: 8px; height: 8px; flex: none; box-sizing: border-box; border-radius: 99px; background: var(--brand); }
.ms-motif-node:last-child .ms-motif-dot { border: 1.5px solid var(--motif-check); box-shadow: 0 0 6px color-mix(in srgb, var(--brand) 40%, transparent); }
.ms-motif-label { display: grid; gap: 1px; flex: 1; min-width: 0; white-space: nowrap; }
.ms-motif-label small { font-size: 8px; color: var(--motif-label); }
.ms-motif-label strong { font-size: 11px; color: var(--motif-fg); }
.ms-motif-node:last-child strong { color: var(--brand-mint); }
.ms-motif-check { width: 13px; height: 13px; flex: none; fill: none; stroke: var(--motif-check); stroke-width: 1.6; stroke-linecap: round; }
.ms-motif-check path { stroke-dasharray: 1 1; }
.ms-motif-line { width: 2px; height: 16px; margin-left: 3px; border-radius: 1px; background: var(--motif-line); }
.ms-motif-on { padding: 2px 6px; border-radius: var(--radius-sm); background: var(--success-bg); color: var(--success-fg); font: var(--type-micro); }
/* Figma's starts, % of 2.2 s: dots 4.5 / 22.7 / 43.2, lines 11.4 / 31.8, checks 15.9 / 34.1. */
.ms-motif > :nth-child(1) .ms-motif-dot { --a: 4.545; --b: 13.636; } .ms-motif > :nth-child(2) { --a: 11.364; --b: 25; }
.ms-motif > :nth-child(3) .ms-motif-dot { --a: 22.727; --b: 34.091; } .ms-motif > :nth-child(4) { --a: 31.818; --b: 45.455; }
.ms-motif > :nth-child(5) .ms-motif-dot { --a: 43.182; --b: 54.545; }
.ms-motif > :nth-child(1) .ms-motif-check path { --a: 15.909; --b: 29.545; } .ms-motif > :nth-child(3) .ms-motif-check path { --a: 34.091; --b: 47.727; }
/* One keyframe each, placed on the timeline: delay a%, run (b - a)%. */
.ms-motif-dot, .ms-motif-line { animation: ms-motif-on calc(var(--motion-celebrate) * (var(--b) - var(--a)) / 100) var(--ease-out) calc(var(--motion-celebrate) * var(--a) / 100) both; }
.ms-motif-check path { animation: ms-motif-draw calc(var(--motion-celebrate) * (var(--b) - var(--a)) / 100) var(--ease-out) calc(var(--motion-celebrate) * var(--a) / 100) both; }
@keyframes ms-motif-on { from { opacity: .22; } to { opacity: 1; } }
@keyframes ms-motif-draw { from { stroke-dasharray: 0 1; visibility: hidden; } to { stroke-dasharray: 1 1; visibility: visible; } }

/* ---- Unplugged illustration (1:13443, Figma's 3.2 s cohort on 1:13194):
   plug and socket ease 1.5 px apart along their -42 deg frame and back
   (50%), the sparkles dim to .35 in turn. Figma loops it; it plays once
   when inserted and rests on its last frame, which is its first: the
   static, reduced-motion picture (proposed). */
.ms-plug { display: block; width: 220px; height: 132px; overflow: visible; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.ms-plug-halo { fill: var(--celebrate-halo); stroke: color-mix(in srgb, var(--celebrate-ring) 50%, var(--surface)); }
.ms-plug-arc { stroke: color-mix(in srgb, var(--celebrate-ring) 30%, var(--surface)); }
.ms-plug-cord { stroke: url(#ms-plug-cord); stroke-width: 3.5; }
.ms-plug-body { fill: var(--celebrate-fill); stroke: var(--plug-ink); stroke-width: 1.4; }
.ms-plug-collar { fill: var(--accent-tint); stroke: var(--plug-ink); stroke-width: 1.3; }
.ms-plug-pin { stroke: var(--plug-ink); stroke-width: 1.6; }
.ms-plug-shine { stroke: var(--celebrate-ring); }
.ms-plug-spark { stroke: var(--celebrate-spark); }
.ms-plug * { animation-duration: var(--motion-unplug); animation-timing-function: var(--ease-standard); animation-fill-mode: both; }
.ms-plug-plug { animation-name: ms-plug-out; }
.ms-plug-socket { animation-name: ms-socket-out; }
.ms-plug-spark-left { animation-name: ms-plug-spark-left; }
.ms-plug-spark-top { animation-name: ms-plug-spark-top; }
.ms-plug-spark-right { animation-name: ms-plug-spark-right; }
@keyframes ms-plug-out { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(-1.5px, 1.5px); } }
@keyframes ms-socket-out { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(1.5px, -1.5px); } }
@keyframes ms-plug-spark-left { 0%, 100% { opacity: 1; } 34.375% { opacity: .35; } }
@keyframes ms-plug-spark-top { 0%, 100% { opacity: 1; } 45.313% { opacity: .35; } }
@keyframes ms-plug-spark-right { 0%, 100% { opacity: 1; } 56.25% { opacity: .35; } }

/* ---- Empty and error states: the shell; illustration and copy belong to
   each page. Icon 40 in a 64 tile, title, body, optional action. The error
   state is not in Figma (proposed): the alert tone and a Secondary "Try again". */
.ms-state { display: grid; justify-items: center; gap: var(--space-2); padding: var(--space-7) var(--space-5); text-align: center; }
.ms-state-icon { display: grid; place-items: center; width: 64px; height: 64px; margin-bottom: var(--space-2); border-radius: var(--radius-2xl); background: var(--surface-sunken); color: var(--fg-muted); }
.ms-state-icon svg { width: 40px; height: 40px; }
.ms-state-art { margin-bottom: var(--space-2); }
.ms-state-title { margin: 0; font: var(--type-title); color: var(--fg); }
.ms-state-body { max-width: 42ch; margin: 0; font: var(--type-body-sm); color: var(--fg-muted); }
.ms-state-action { margin-top: var(--space-3); }
.ms-state-error .ms-state-icon { background: color-mix(in srgb, var(--alert-dot) 16%, var(--surface)); color: var(--danger-fg); }

/* ---- Reduced motion ---- */
@media (prefers-reduced-motion: reduce) {
  .content:has([data-loading]) + .page-loader { animation-duration: 0s; } /* still waits out the delay */
  .ms-org-loader-grid i, .ms-org-loader-text, .ms-org-loader-step, .ms-org-loader-phases > *, .ms-running *, .ms-success *, .ms-motif *, .ms-plug * { animation: none !important; }
  .ms-org-loader[data-mode="timeline"] .ms-org-loader-phases > :first-child { opacity: 1; }
  .ms-running-dots i { opacity: .6; }
}
:root[data-motion="reduce"] :is(.ms-org-loader-grid i, .ms-org-loader-text, .ms-org-loader-step, .ms-org-loader-phases > *, .ms-running *, .ms-success *, .ms-motif *, .ms-plug *) { animation: none !important; }
:root[data-motion="reduce"] .ms-org-loader[data-mode="timeline"] .ms-org-loader-phases > :first-child { opacity: 1; }
:root[data-motion="reduce"] .ms-running-dots i { opacity: .6; }
:root[data-motion="reduce"] .content:has([data-loading]) + .page-loader { animation-duration: 0s; }
