/* ---------- Contact map: identity on the left, map on the right ------------
   A 4fr / 7fr grid with a 6rem gap — the same ratio and the same gap that
   .cnt-form__grid and .cnt-small__grid above already use, so the form card, the audit
   field and the map share one left edge. Rhythm comes from repeating a number.

   The background is --stone2 because the .cnt-form gradient above ends exactly on
   that color, so the transition has no seam. Without this the body (--ink) would show.

   No top padding: .cnt-small above already carries 8rem at the bottom. The bottom 9rem is the
   gap to the footer.

   The map frame intentionally has no aspect-ratio: the SVG carries its own (881 x 405.9)
   and the height is computed from the width, so the drawing never stretches at any width. */
.cnt-map { background: var(--stone2); color: var(--ink); padding-block: 0 9rem; }
.cnt-map__grid {
  display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 7fr);
  gap: 6rem; align-items: start;
}
/* The block is exactly as wide as the name, so the mark centers ABOVE the heading — the same
   composition as in the address card the pin brings in. */
.cnt-map__id { width: max-content; max-width: 100%; }
.cnt-map__mark { display: block; height: 3.4rem; width: auto; margin-inline: auto; }
.cnt-map__name {
  font-size: 3.2rem; line-height: 1.05; letter-spacing: -0.005em;
  font-weight: var(--w-h2); margin-top: 1.6rem;   /* same scale as .cnt-form__title */
}
.cnt-map__frame { border-radius: var(--r-14); overflow: hidden; }
.cnt-map__frame > svg.gbmap { width: 100%; height: auto; display: block; }

/* ---------- Stacked state (below 1024) -------------------------------------
   When the columns drop one below the other, the role of both elements changes:

   The map goes edge to edge. Inside the container at 390 px it would stay 321 px wide
   because .ctr takes 2 x 2.8125rem, and on a phone that is 21% of the width and 30 px
   of height the map needs. .ctr is width:100% without max-width, so a negative margin
   of that same value lands exactly on the screen edge. The radius is removed — rounded
   corners touching the screen edge look like a bug, not a frame.

   The identity steps back and centers. On desktop the mark is 3.4rem against a
   3.2rem name, i.e. slightly larger than the heading — there it stands alone in its
   column and carries it. Stacked, above a full-width band, the mark returns to 1.8rem
   and the name drops to 1.82rem — a ratio of 0.99, so mark and name are practically the same height. The mark-to-name gap follows
   (1.6rem -> 1.1rem).

   The text stays inset in the container while the map is full width — the standard pairing
   "inset text, media to the edge".                                          */
@media (max-width: 1023px) {
  /* No bottom padding — the map touches the footer. The two darks merge (#16181C and
     #121317 are four shades apart), so the seam is invisible and the bottom of the page reads as
     one dark zone that closes it. On a phone that also saves 6rem of
     height. The entry into the section still exists — the light block with the identity above. */
  .cnt-map { padding-block: 0; }
  .cnt-map__grid { grid-template-columns: 1fr; gap: 3rem; }

  /* The identity centers above the band. The block is as wide as the name, so
     margin-inline: auto puts it in the middle, and the mark stays centered within it. */
  .cnt-map__id { margin-inline: auto; }
  .cnt-map__name { font-size: 1.82rem; margin-top: 1.1rem; }
  .cnt-map__mark { height: 1.8rem; }

  .cnt-map__frame { margin-inline: -2.8125rem; border-radius: 0; }
}


/* ---------- Animation: three arrivals at our address, looping ---------------

   Routes were computed with Dijkstra over the drawn road network; legs 2 and 3 pass through
   set waypoints because plain Dijkstra finds shortcuts that bypass SW 200th St.

     leg    length   duration   movement              card
     sw    641.6 px   6.99 s   movement   0.00–  6.99 s   card gone   9.94 s
     ne    661.9 px   7.21 s   movement   6.94– 14.15 s   card gone  17.10 s
     n     746.0 px   8.13 s   movement  14.10– 22.23 s   card gone   3.00 s

   Speed 91.8 px/s for all three. The card stays for 2 s after arrival.
   Each next leg starts 3 s before the previous leg's card disappears —
   including the "third -> first" transition, so the rhythm is the same across the loop seam. Cycle
   22.18 s. The tail of the third leg crosses the cycle boundary; that is why all keyframes are
   computed as a function of phase with (p - start) mod TOTAL.

   Three separate traveling pins — since the legs intersect, a single element would have to be
   in two places at once.

   The animated elements live in a separate thin SVG layer over the map, with the same
   viewBox. Chrome does not composite transform on a <g> inside an SVG, so in the large
   map every frame would force repainting all 782 paths.                        */

.cnt-map__frame { position: relative; }
.gbmap-fx { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }

.cnt-map .gbmap__drive,
.cnt-map .gbmap__card { opacity: 0; }
.cnt-map .gbmap__drive { transform-box: view-box; transform-origin: 0 0; }
.cnt-map .gbmap__drive--1 { transform: translate(1.0px, 290.0px); }
.cnt-map .gbmap__drive--2 { transform: translate(219.0px, 90.0px); }
.cnt-map .gbmap__drive--3 { transform: translate(878.0px, 229.0px); }
/* The pin grows around its TIP, not its center — the tip is what points at the address. */
.cnt-map .gbmap__location-pin { transform-box: view-box; transform-origin: 440.5px 244.875px; }
.cnt-map .gbmap__card { transform-box: view-box; transform-origin: 440.5px 198px; }

.cnt-map.is-armed.is-in .gbmap__drive--1 { animation: gbmap-drive-1 22.18s linear infinite both; }
.cnt-map.is-armed.is-in .gbmap__drive--2 { animation: gbmap-drive-2 22.18s linear infinite both; }
.cnt-map.is-armed.is-in .gbmap__drive--3 { animation: gbmap-drive-3 22.18s linear infinite both; }
.cnt-map.is-armed.is-in .gbmap__location-pin { animation: gbmap-pin 22.18s linear infinite both; }
.cnt-map.is-armed.is-in .gbmap__card { animation: gbmap-card 22.18s linear infinite both; }

/* Routes were recomputed for the new address (7901 4th St N Ste 300, St. Petersburg):
   Dijkstra over the skeleton of the drawn road network. The timing skeleton is the same as before —
   22.18s cycle, same appear/arrive/disappear percentages; only the coordinates change.
   gbmap-pin and gbmap-card are untouched: they carry only scale/translateY, no coordinates. */
@keyframes gbmap-drive-1 {
  0% { opacity: 0.0; transform: translate(1.0px, 290.0px); }
  0.541% { opacity: 1.0; transform: translate(1.0px, 290.0px); }
  2.9495% { opacity: 1.0; transform: translate(39.0px, 290.0px); }
  3.4873% { opacity: 1.0; transform: translate(45.0px, 296.0px); }
  3.8458% { opacity: 1.0; transform: translate(49.0px, 292.0px); }
  4.6722% { opacity: 1.0; transform: translate(48.0px, 279.0px); }
  16.5251% { opacity: 1.0; transform: translate(235.0px, 277.0px); }
  18.3401% { opacity: 1.0; transform: translate(263.0px, 283.0px); }
  28.0392% { opacity: 1.0; transform: translate(416.0px, 280.0px); }
  28.3977% { opacity: 1.0; transform: translate(420.0px, 276.0px); }
  29.2217% { opacity: 1.0; transform: translate(420.0px, 263.0px); }
  29.6698% { opacity: 1.0; transform: translate(425.0px, 258.0px); }
  30.6227% { opacity: 1.0; transform: translate(440.0px, 259.0px); }
  31.5169% { opacity: 1.0; transform: translate(440.5px, 244.9px); }
  33.0949% { opacity: 0.0; transform: translate(440.5px, 244.9px); }
  33.1851% { opacity: 0.0; transform: translate(1.0px, 290.0px); }
  100% { opacity: 0.0; transform: translate(1.0px, 290.0px); }
}
@keyframes gbmap-drive-2 {
  0% { opacity: 0.0; transform: translate(219.0px, 90.0px); }
  31.2915% { opacity: 0.0; transform: translate(219.0px, 90.0px); }
  31.6491% { opacity: 0.661; transform: translate(219.0px, 90.0px); }
  31.8325% { opacity: 1.0; transform: translate(219.0px, 90.0px); }
  32.3867% { opacity: 1.0; transform: translate(215.0px, 83.0px); }
  34.0364% { opacity: 1.0; transform: translate(215.0px, 59.0px); }
  35.4816% { opacity: 1.0; transform: translate(236.0px, 58.0px); }
  42.2181% { opacity: 1.0; transform: translate(236.0px, 156.0px); }
  42.7185% { opacity: 1.0; transform: translate(243.0px, 158.0px); }
  43.242% { opacity: 1.0; transform: translate(246.0px, 165.0px); }
  55.5466% { opacity: 1.0; transform: translate(425.0px, 166.0px); }
  61.871% { opacity: 1.0; transform: translate(426.0px, 258.0px); }
  62.8358% { opacity: 1.0; transform: translate(440.0px, 259.0px); }
  63.8056% { opacity: 1.0; transform: translate(440.5px, 244.9px); }
  65.3836% { opacity: 0.0; transform: translate(440.5px, 244.9px); }
  65.4738% { opacity: 0.0; transform: translate(219.0px, 90.0px); }
  100% { opacity: 0.0; transform: translate(219.0px, 90.0px); }
}
@keyframes gbmap-drive-3 {
  0% { opacity: 1.0; transform: translate(440.0px, 259.0px); }
  0.2254% { opacity: 1.0; transform: translate(440.5px, 244.9px); }
  1.8035% { opacity: 0.0; transform: translate(440.5px, 244.9px); }
  1.8936% { opacity: 0.0; transform: translate(878.0px, 229.0px); }
  63.5801% { opacity: 0.0; transform: translate(878.0px, 229.0px); }
  64.033% { opacity: 0.837; transform: translate(878.0px, 229.0px); }
  64.1212% { opacity: 1.0; transform: translate(878.0px, 229.0px); }
  65.8653% { opacity: 1.0; transform: translate(845.0px, 227.0px); }
  67.3349% { opacity: 1.0; transform: translate(819.0px, 217.0px); }
  68.9007% { opacity: 1.0; transform: translate(794.0px, 201.0px); }
  69.27% { opacity: 1.0; transform: translate(787.0px, 201.0px); }
  73.0742% { opacity: 1.0; transform: translate(727.0px, 241.0px); }
  73.4546% { opacity: 1.0; transform: translate(723.0px, 247.0px); }
  74.0514% { opacity: 1.0; transform: translate(731.0px, 255.0px); }
  74.6932% { opacity: 1.0; transform: translate(729.0px, 267.0px); }
  75.9438% { opacity: 1.0; transform: translate(708.0px, 278.0px); }
  77.797% { opacity: 1.0; transform: translate(673.0px, 275.0px); }
  78.5578% { opacity: 1.0; transform: translate(665.0px, 287.0px); }
  79.3492% { opacity: 1.0; transform: translate(650.0px, 287.0px); }
  80.0102% { opacity: 1.0; transform: translate(639.0px, 281.0px); }
  80.718% { opacity: 1.0; transform: translate(627.0px, 287.0px); }
  81.562% { opacity: 1.0; transform: translate(611.0px, 287.0px); }
  81.8957% { opacity: 1.0; transform: translate(609.0px, 293.0px); }
  82.7925% { opacity: 1.0; transform: translate(592.0px, 293.0px); }
  83.6513% { opacity: 1.0; transform: translate(580.0px, 282.0px); }
  86.606% { opacity: 1.0; transform: translate(524.0px, 283.0px); }
  89.1432% { opacity: 1.0; transform: translate(521.0px, 331.0px); }
  93.2056% { opacity: 1.0; transform: translate(444.0px, 330.0px); }
  93.9134% { opacity: 1.0; transform: translate(438.0px, 342.0px); }
  94.1771% { opacity: 1.0; transform: translate(433.0px, 342.0px); }
  94.6635% { opacity: 1.0; transform: translate(427.0px, 335.0px); }
  98.6204% { opacity: 1.0; transform: translate(428.0px, 260.0px); }
  99.2557% { opacity: 1.0; transform: translate(440.0px, 259.0px); }
  100% { opacity: 1.0; transform: translate(440.0px, 259.0px); }
}

@keyframes gbmap-pin {
  0.0% { transform: scale(1.0); }
  0.2254% { transform: scale(1.0); }
  2.4798% { transform: scale(1.2); }
  11.948% { transform: scale(1.2); }
  13.7514% { transform: scale(1.0); }
  13.8416% { transform: scale(1.0); }
  31.5169% { transform: scale(1.0); }
  33.7712% { transform: scale(1.2); }
  43.2395% { transform: scale(1.2); }
  45.0429% { transform: scale(1.0); }
  45.1331% { transform: scale(1.0); }
  63.8056% { transform: scale(1.0); }
  66.0599% { transform: scale(1.2); }
  75.5281% { transform: scale(1.2); }
  77.3316% { transform: scale(1.0); }
  77.4218% { transform: scale(1.0); }
  100.0% { transform: scale(1.0); }
}

@keyframes gbmap-card {
  0.0% { opacity: 0.0; transform: translateY(7.0px) scale(0.96); }
  0.2254% { opacity: 0.0; transform: translateY(7.0px) scale(0.96); }
  0.6763% { opacity: 0.0; transform: translateY(7.0px) scale(0.96); }
  2.9306% { opacity: 1.0; transform: translateY(0.0px) scale(1.0); }
  11.948% { opacity: 1.0; transform: translateY(0.0px) scale(1.0); }
  13.526% { opacity: 0.0; transform: translateY(-4.0px) scale(0.98); }
  13.7514% { opacity: 0.0; transform: translateY(-4.0px) scale(0.98); }
  13.8416% { opacity: 0.0; transform: translateY(7.0px) scale(0.96); }
  31.5169% { opacity: 0.0; transform: translateY(7.0px) scale(0.96); }
  31.9678% { opacity: 0.0; transform: translateY(7.0px) scale(0.96); }
  34.2221% { opacity: 1.0; transform: translateY(0.0px) scale(1.0); }
  43.2395% { opacity: 1.0; transform: translateY(0.0px) scale(1.0); }
  44.8175% { opacity: 0.0; transform: translateY(-4.0px) scale(0.98); }
  45.0429% { opacity: 0.0; transform: translateY(-4.0px) scale(0.98); }
  45.1331% { opacity: 0.0; transform: translateY(7.0px) scale(0.96); }
  63.8056% { opacity: 0.0; transform: translateY(7.0px) scale(0.96); }
  64.2564% { opacity: 0.0; transform: translateY(7.0px) scale(0.96); }
  66.5108% { opacity: 1.0; transform: translateY(0.0px) scale(1.0); }
  75.5281% { opacity: 1.0; transform: translateY(-0.0px) scale(1.0); }
  77.1062% { opacity: 0.0; transform: translateY(-4.0px) scale(0.98); }
  77.3316% { opacity: 0.0; transform: translateY(7.0px) scale(0.96); }
  77.4218% { opacity: 0.0; transform: translateY(7.0px) scale(0.96); }
  100.0% { opacity: 0.0; transform: translateY(7.0px) scale(0.96); }
}
