/* ══════════════════════════════════════════════════════════════════════════
   THE PAYMENTS TRACE — background motion
   site-v2/assets/css/motion.css

   Load after site.css. Everything here is layout for the two canvas layers;
   there is no colour in this file, because the canvases paint themselves from
   the theme tokens.
   ══════════════════════════════════════════════════════════════════════════ */

:root {
  /* one semantic stack, so nothing here ever needs an arbitrary 9999 */
  --z-motion-fixed: 0;   /* the ambient globe, behind everything */
  --z-motion-hero: 0;    /* the hero mark, behind the hero's own content */
  --z-hero-content: 1;
}

/* ── the shared canvas ───────────────────────────────────────────────────
   Decoration, and it must behave like it: hidden from assistive technology,
   never in the way of a click, never selectable. The globe's drag is bound on
   window and hit-tested against the sphere, so the canvas itself stays inert
   and a text selection over the article is never stolen. */
.trace-motion-canvas {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  pointer-events: none;
  user-select: none;
}

/* ── the home hero ───────────────────────────────────────────────────────
   The layer is absolutely positioned inside the hero section, so it scrolls
   away with it and stops animating when it does. The hero's own content sits
   above it. */
.hero { position: relative; }
.hero > .wrap,
.hero .hero-grid { position: relative; z-index: var(--z-hero-content); }

.motion-hero {
  position: absolute;
  inset: 0;
  overflow: hidden;
  z-index: var(--z-motion-hero);
  pointer-events: none;
}

/* ── the ambient globe ───────────────────────────────────────────────────
   Fixed, full viewport, behind every other layer on the page. It is the only
   element on the site with a negative-adjacent stacking role, so it is given
   its own isolation rather than relying on source order. */
.motion-ambient {
  position: fixed;
  inset: 0;
  overflow: hidden;
  z-index: var(--z-motion-fixed);
  pointer-events: none;
  isolation: isolate;
}
/* the page content has to sit above it, and a fixed layer at z-index 0 only
   loses to positioned content */
body > header,
body > main,
body > footer,
main > * { position: relative; z-index: 1; }

/* the cursor is the only affordance saying the globe is a physical object */
html.trace-has-globe .motion-ambient { cursor: grab; }
html.trace-grabbing,
html.trace-grabbing * { cursor: grabbing !important; }
/* a drag that leaves a half-selected paragraph behind it is a bug, not a
   flourish. motion.js also preventDefaults the pointerdown; this catches the
   case where a browser starts the selection anyway. */
html.trace-grabbing, html.trace-grabbing * { user-select: none !important; }

/* ── no JavaScript, no canvas, no change ─────────────────────────────────
   The layers are empty divs until motion.js fills them, so a page with JS
   disabled is exactly the page without motion. Nothing is gated on a class. */

@media (prefers-reduced-motion: reduce) {
  /* motion.js already renders a single resolved frame and never starts a loop.
     This is belt and braces for the cursor affordance only. */
  html.trace-has-globe .motion-ambient { cursor: default; }
}

/* Below the desktop breakpoint the globe is centred behind the copy and the
   drag is disabled in JS, so the grab cursor would be a lie. */
@media (max-width: 1000px) {
  html.trace-has-globe .motion-ambient { cursor: default; }
}

/* Print: never. */
@media print {
  .motion-hero, .motion-ambient { display: none !important; }
}
