/* ==================================================================
   GPS live-tracking overlay — a looping two-act story over the map
   screenshot. Reusable across the homepage bento, the product page and
   the how-it-works feature, so it lives in its own stylesheet.

   Markup contract: an element with class .phone-screen wraps the map
   <img> (so the overlay sizes to the screenshot exactly), with the
   .gps-overlay SVG layer as its sibling. Works inside any phone frame
   (.phone-mock--gps, .hiw-phone, …).

   ONE shared master timeline (--gps-cycle) keeps both acts in sync and
   looping seamlessly:
     Act 1  (0% → 50%)  Stormi walks a route, drawing a persistent trace.
     Act 2  (50% → 100%) a geofence expands around her; she wanders out
                          and triggers a red breach alert.
   Each element is opacity:0 outside its act, so the acts never overlap.
   ================================================================== */
.phone-screen {
  position: relative;
  display: block;
  line-height: 0;
}
.gps-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  --gps-cycle: 32s;                     /* whole two-act loop */
}
.gps-overlay__svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  overflow: visible;
}

/* ── Act 1 · route trace ───────────────────────────────────────────
   A constant line that DRAWS progressively behind the avatar and stays,
   then fades once the loop is complete. pathLength="100" normalises the
   geometry so the dash maths is simple. */
.gps-overlay__trail {
  fill: none;
  stroke: #5CC8FF;
  stroke-width: 8;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 100;               /* whole path = one dash */
  stroke-dashoffset: 100;              /* start fully hidden, draw to 0 */
  filter: drop-shadow(0 0 4px rgba(92, 200, 255, 0.85));
  animation: gps-trace var(--gps-cycle) linear infinite;
}
@keyframes gps-trace {
  0%   { stroke-dashoffset: 100; opacity: 1; }   /* empty */
  2%   { stroke-dashoffset: 100; opacity: 1; }   /* hold for avatar fade-in */
  36%  { stroke-dashoffset: 0;   opacity: 1; }   /* drawn, in step with walk */
  45%  { stroke-dashoffset: 0;   opacity: 1; }   /* hold the full route */
  50%  { stroke-dashoffset: 0;   opacity: 0; }   /* fade out → Act 2 */
  100% { stroke-dashoffset: 0;   opacity: 0; }   /* stay hidden in Act 2 */
}

/* Avatar marker — rides the route; the head of the line sits on it. */
.gps-overlay__marker {
  offset-path: path("M200 980C250 860 180 760 300 700C400 650 360 520 250 470C160 430 200 300 330 290C450 281 520 380 460 480C410 565 480 650 440 760C410 850 320 1070 200 980Z");
  offset-rotate: 0deg;
  offset-distance: 0%;
  animation: gps-walk var(--gps-cycle) linear infinite;
}
@keyframes gps-walk {
  0%   { offset-distance: 0%;   opacity: 0; }    /* acquire signal */
  2%   { offset-distance: 0%;   opacity: 1; }
  36%  { offset-distance: 100%; opacity: 1; }    /* slow walk, draws the line */
  45%  { offset-distance: 100%; opacity: 1; }    /* rest at the end */
  50%  { offset-distance: 100%; opacity: 0; }    /* fade out → Act 2 */
  100% { offset-distance: 100%; opacity: 0; }    /* stay hidden in Act 2 */
}
.gps-overlay__ring {
  fill: none;
  stroke: #fff;
  stroke-width: 5;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.35));
}
.gps-overlay__pulse {
  fill: rgba(92, 200, 255, 0.45);
  transform-box: fill-box;
  transform-origin: center;
  animation: gps-pulse 2.4s ease-out infinite;
}
@keyframes gps-pulse {
  0%   { transform: scale(1);   opacity: 0.55; }
  70%  { transform: scale(2.6); opacity: 0;    }
  100% { transform: scale(2.6); opacity: 0;    }
}

/* ── Act 2 · geofence + breach ─────────────────────────────────────
   The safe-zone circle scales up around its own centre, holds, then the
   pet leaves and everything flashes red. Hidden during Act 1. */
.gps-fence__zone {
  fill: rgba(52, 199, 89, 0.10);
  stroke: #34C759;
  stroke-width: 6;
  stroke-dasharray: 16 14;
  vector-effect: non-scaling-stroke;   /* keep dashes crisp while growing */
  transform-box: fill-box;
  transform-origin: center;
  opacity: 0;
  animation: gps-fence-zone var(--gps-cycle) linear infinite;
}
@keyframes gps-fence-zone {
  0%   { opacity: 0; transform: scale(0);    stroke: #34C759; fill: rgba(52,199,89,0.10); }
  50%  { opacity: 0; transform: scale(0);    stroke: #34C759; fill: rgba(52,199,89,0.10); }
  53%  { opacity: 0; transform: scale(0.2); }
  61%  { opacity: 1; transform: scale(1.06); }  /* gentle overshoot */
  64%  { opacity: 1; transform: scale(1);   }
  78%  { opacity: 1; transform: scale(1);    stroke: #34C759; fill: rgba(52,199,89,0.10); }
  79%  { opacity: 1; stroke: #FF3B30; fill: rgba(255,59,48,0.16); }  /* breach */
  82%  { opacity: 0.45; }
  85%  { opacity: 1; }
  88%  { opacity: 0.45; }
  91%  { opacity: 1; }
  94%  { opacity: 0; stroke: #FF3B30; fill: rgba(255,59,48,0.16); }  /* fade out */
  100% { opacity: 0; transform: scale(1); }
}

/* The pet inside the fence — fades in centred, then walks past the edge. */
.gps-fence__marker {
  offset-path: path("M360 560L600 380");
  offset-rotate: 0deg;
  offset-distance: 0%;
  opacity: 0;
  animation: gps-fence-move var(--gps-cycle) linear infinite;
}
@keyframes gps-fence-move {
  0%   { offset-distance: 0%;   opacity: 0; }
  50%  { offset-distance: 0%;   opacity: 0; }
  53%  { offset-distance: 0%;   opacity: 1; }   /* appear at centre */
  68%  { offset-distance: 0%;   opacity: 1; }   /* sit safe inside */
  82%  { offset-distance: 100%; opacity: 1; }   /* wander out (crosses ~79%) */
  94%  { offset-distance: 100%; opacity: 1; }
  100% { offset-distance: 100%; opacity: 0; }
}
.gps-fence__ring {
  fill: none;
  stroke: #fff;
  stroke-width: 5;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.35));
  animation: gps-fence-ring var(--gps-cycle) linear infinite;
}
@keyframes gps-fence-ring {
  0%   { stroke: #fff;     opacity: 1; }
  78%  { stroke: #fff;     opacity: 1; }
  79%  { stroke: #FF3B30;  opacity: 1; }   /* turn red on breach */
  82%  { opacity: 0.3; }
  85%  { opacity: 1; }
  88%  { opacity: 0.3; }
  91%  { opacity: 1; }
  94%  { stroke: #FF3B30;  opacity: 1; }
  100% { stroke: #fff;     opacity: 1; }
}
.gps-fence__alert {
  fill: none;
  stroke: #FF3B30;
  stroke-width: 4;
  vector-effect: non-scaling-stroke;
  transform-box: fill-box;
  transform-origin: center;
  opacity: 0;
  animation: gps-fence-alert var(--gps-cycle) linear infinite;
}
@keyframes gps-fence-alert {              /* two red rings ping outward */
  0%     { opacity: 0;   transform: scale(1); }
  78%    { opacity: 0;   transform: scale(1); }
  79%    { opacity: 0.7; transform: scale(1); }
  85%    { opacity: 0;   transform: scale(3); }
  85.5%  { opacity: 0.7; transform: scale(1); }
  91%    { opacity: 0;   transform: scale(3); }
  100%   { opacity: 0;   transform: scale(1); }
}

/* Respect reduced-motion: freeze Act 1 into a completed-route snapshot
   and drop the animated geofence act entirely. */
@media (prefers-reduced-motion: reduce) {
  .gps-overlay__trail {
    animation: none;
    stroke-dasharray: none;
    stroke-dashoffset: 0;
  }
  .gps-overlay__marker {
    animation: none;
    offset-distance: 62%;
  }
  .gps-overlay__pulse { animation: none; opacity: 0; }
  .gps-fence__zone,
  .gps-fence__marker,
  .gps-fence__ring,
  .gps-fence__alert { animation: none; opacity: 0; }
}
