/* src/modules/demo/demoTour.css — the scripted demo's pointer.
   Only the hand is styled here; the tour drives the app's own real controls, which keep their own
   appearance. A demo that restyled what it was demonstrating would be showing a different app. */

.demo-tour-hand {
  /* Sits above the clipboard overlay, which is the surface the tour spends most of its time on. */
  position: fixed;
  z-index: 9999;
  top: 0;
  left: 0;
  /* Offset so the FINGERTIP lands on the point the pointer was moved to, not the middle of the
     hand. The drawn finger is a column at x≈10.5 of the 26-wide box with its tip at y≈0.5, so those
     are the numbers — -6/-4 put the box's CORNER on the target, which is a knuckle's width away and
     was visible as soon as the tap rings were drawn at the real point. */
  margin: -1px 0 0 -10px;
  line-height: 0;
  opacity: 0;
  /* Never intercepts the tap it is illustrating — the player clicks the real control underneath. */
  pointer-events: none;
  transform: translate3d(var(--hand-x, 0), var(--hand-y, 0), 0);
  transition: transform 0.42s cubic-bezier(0.33, 0.1, 0.25, 1), opacity 0.2s ease;
}
/* DRAGGING: the hand is not travelling TO a control any more, it is the finger that is moving the
   screen, so it has to be exactly where the pointer event it is sending says it is. The 0.42s glide
   above would leave it most of half a second behind every point of the path — and the demo's own
   test asserts the hand is over the place each event lands. It keeps its fade, which is not a
   position. */
.demo-tour-hand.is-dragging {
  transition: opacity 0.2s ease;
}
/* Pressed for the whole drag, the way the tap's own press looks, so a viewer reads a finger held
   down and moved rather than a hand sliding over the glass. */
.demo-tour-hand.is-dragging svg {
  transform: scale(0.88);
}
/* Light fill with a dark edge, so the hand stays legible over both a pale dashboard and the dark
   live-session overlay without knowing which it is on. */
.demo-tour-hand svg {
  display: block;
  fill: rgba(255, 255, 255, 0.96);
  stroke: rgba(15, 23, 42, 0.55);
  stroke-width: 1.1;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.45));
}

.demo-tour-hand.is-visible {
  opacity: 0.92;
}

/* The tap is the HAND moving: a short press toward the screen and back, which is what the gesture
   actually looks like.

   Anchored at the FINGERTIP (reported 2026-08-18: "finger is jumping after every click"). Scaling
   about the element's centre drags the tip toward the palm and back — a few pixels of travel at the
   exact moment the eye is on the contact point, which reads as the finger hopping rather than
   pressing. The tip is drawn at the top-left of the box, so that is the origin. */
/* The press is animated on the DRAWING, not on the positioned wrapper. The wrapper carries the
   translate that puts the hand on the control, and `transform-origin: top left` there scales that
   translation too — which moved the hand 17px per tap, a bigger version of the jump this fixes. The
   svg has no translation of its own, so scaling it about its top-left corner moves nothing but the
   drawing, and the fingertip drawn at that corner stays exactly where it touched. */
.demo-tour-hand.is-tapping svg {
  transform-origin: top left;
  animation: demo-tour-tap 0.36s ease-out;
}

@keyframes demo-tour-tap {
  0%,
  100% {
    scale: 1;
  }
  55% {
    scale: 0.82;
  }
}

/* The tour still runs and still asserts — only the travel and the pulse stop. Someone who asked for
   less motion wants the demonstration, not a static screen. */
@media (prefers-reduced-motion: reduce) {
  .demo-tour-hand {
    transition: opacity 0.2s ease;
  }
  .demo-tour-hand.is-tapping {
    animation: none;
  }
}

/* The mark a tap leaves where it landed (wanted 2026-08-18). Sits with the hand rather than in the
   walkthrough's stylesheet because both the scripted demo and "Show me" produce it — it belongs to
   the pointer, not to the guide. Never intercepts anything, and honours reduced motion by simply
   not being drawn: a static ring left on screen would say a tap is still happening. */
.demo-tour-ripple {
  position: fixed;
  z-index: 9998;
  /* Placed with left/top and centred with a translate, NOT with a translate3d of the coordinates:
     the ring also animates `scale`, and composing the two moved the mark tens of pixels off the
     point it was meant to mark. With the offset in the transform, the centre stays put at every
     scale. */
  left: var(--ripple-x, 0);
  top: var(--ripple-y, 0);
  /* Bigger and brighter than the first attempt, which was reported as not noticeable enough: on a
     laptop this is the only thing saying a tap happened, and it is competing with whatever the app
     itself does in response. */
  width: 26px;
  height: 26px;
  border-radius: 50%;
  /* The theme's own accent, not white (wanted 2026-08-18): white reads as a screenshot artefact on
     a pale theme and as glare on a dark one, while the app's accent says LibrePT is doing this.
     The fallback matters — this file is loaded by the demo alone, and a theme that somehow did not
     define --primary would otherwise draw nothing at all. */
  border: 3px solid var(--primary, #6366f1);
  box-shadow: 0 0 16px color-mix(in srgb, var(--primary, #6366f1) 70%, transparent), inset 0 0 10px
    color-mix(in srgb, var(--primary, #6366f1) 45%, transparent);
  pointer-events: none;
  /* Centred with a MARGIN, not a translate. The animated `scale` composes outside `transform`, so a
     centring translate is scaled along with the ring — at scale 0.35 the -13px offset became -4.5px
     and the whole set drifted off the contact point as it grew. A margin is laid out before any
     transform runs, so the centre stays put at every size. Half the width, kept in step with it. */
  margin: -13px 0 0 -13px;
  /* Timed by the module that draws the ring, never here (demoPace.js declares it, demoHand.js
     stamps it on). The player waits out one whole ring before it clicks the real control, so a
     duration written in this file could be lengthened past that wait with nothing to catch it —
     which is how the rings ended up playing over the view the tap had already opened. There is
     deliberately NO fallback: no ring is ever built without the property, and a number here would
     be the second source of truth this removed.
     `both`, not `forwards`: the trailing rings start on a delay, and with only a forwards fill they
     were painted at their FULL 26px until their turn came — a hard pop at the contact point, then a
     shrink back to 0.35 to start expanding. Filling backwards holds them at the first keyframe. */
  animation: demo-tour-ripple var(--ripple-ms) cubic-bezier(0.22, 1, 0.36, 1) var(--ripple-delay)
    both;
}
/* The wrapper exists so one timer clears the whole set and the stylesheet can stagger the rings by
   position. It is inert and occupies nothing: every ring inside is position:fixed against the
   viewport. */
.demo-tour-waves {
  position: fixed;
  z-index: 9998;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
  pointer-events: none;
}
/* Three rings, staggered, like something touching a water surface (wanted 2026-08-18). One ring
   reads as a highlight; a set that keeps arriving after the first reads as an impact. Each is
   thinner and fainter than the one before it, which is what stops the group looking like a target
   reticle drawn over the control. Appearance only — WHEN each ring is sent is stamped on by
   demoHand.js, because the player has to wait for the last of them before it taps. */
.demo-tour-ripple:nth-child(2) {
  border-width: 1.5px;
  --ring-peak: 0.75;
}
.demo-tour-ripple:nth-child(3) {
  border-width: 1px;
  --ring-peak: 0.55;
}
/* The wake a held drag leaves, one ring at a time (demoHand.js). Fainter and shorter-reaching than a
   tap's rings: they are left every 24px, and at a tap's full reach they would overlap into a smear
   instead of reading as a line of rings behind the finger. */
.demo-tour-waves.is-wake .demo-tour-ripple {
  border-width: 2px;
  --ring-peak: 0.7;
  --ring-reach: 2.4;
}

/* The ring's brightness is carried INTO the keyframes rather than declared beside them: the
   animation owns opacity for its whole run, so a plain `opacity` on a trailing ring only ever
   showed during its delay and was overwritten the moment it started — the group went out equally
   bright, which is the reticle look the fading exists to avoid. */
@keyframes demo-tour-ripple {
  0% {
    scale: 0.35;
    opacity: var(--ring-peak, 1);
  }
  40% {
    opacity: calc(var(--ring-peak, 1) * 0.9);
  }
  100% {
    scale: var(--ring-reach, 4);
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .demo-tour-ripple {
    display: none;
  }
}
