/* ============================================================
   Atlas replica (`atr`) for /capabilities/atlas
   crew phossil-capability-showcase, 2026-07-26

   Loads AFTER capability.css, which owns `.cap-replica` and the
   marketing-template token base. Tokens only, zero raw hex.

   WHY THE MAP IS HAND-ROLLED. The real Atlas draws on Mapbox GL
   with deck.gl over it (public/atlas.html), and both are external
   origins the marketing CSP does not allow. Loading atlas.css is
   no better: it is 47KB and assumes the authenticated shell. So
   the replica borrows the MECHANISM and the vocabulary, not the
   cartography. The landmass below is invented. It is a diagram of
   how the feature behaves, and it never pretends to be a place.

   WHY THE PINS ARE HTML AND NOT SVG. Two reasons, and the first
   is the real one:
   1. A pin is a control. It has to be a real <button>: focusable,
      Enter-and-Space, 44px. An <svg> child with role="button" is
      the imitation of that, not the thing.
   2. SVG text scales with the viewBox, so a place name inside the
      drawing renders at about four pixels once a 900-unit space is
      squeezed into a phone. Keeping every word in HTML sidesteps
      that entirely: the drawing carries no type at all.
   This also happens to mirror the product, where atlas-map.js
   builds each marker as a DOM element and Mapbox positions it.
   ============================================================ */

.atr {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-sm);
}

/* --- Controls row ----------------------------------------- */

.atr__controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm);
}
.atr__filter {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}
.atr__filter-label {
  font-family: var(--font-sans);
  font-size: 0.85rem;
  color: var(--color-text-muted);
  white-space: nowrap;
}
.atr__select {
  font-family: var(--font-sans);
  font-size: 0.92rem;
  min-height: 44px;
  padding: 0 var(--space-sm);
  border-radius: var(--radius-full);
  border: 1px solid var(--color-accent);
  background: transparent;
  color: var(--color-text-light);
  cursor: pointer;
}
/* The native option list paints on the OS surface, not on the dark
   replica panel, so it needs its own readable pairing. */
.atr__select option {
  color: var(--color-text-primary);
  background: var(--color-surface);
}
.atr__select:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}

.atr__toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  min-height: 44px;
  padding: 0 var(--space-xs);
  font-family: var(--font-sans);
  font-size: 0.9rem;
  color: var(--color-text-light);
  cursor: pointer;
}
.atr__toggle input {
  width: 18px;
  height: 18px;
  accent-color: var(--color-accent);
  cursor: pointer;
}
.atr__toggle input:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}

/* The filtered-to-nobody notice. Never styled as an error: a person
   with no located photos yet is an ordinary state of a real archive. */
.atr__empty {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 0.9rem;
  color: var(--color-accent);
}
.atr__empty[hidden] { display: none; }

/* --- The plot --------------------------------------------- */

.atr__plot {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--color-primary);
}
.atr__svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
/* The drawing stretches with the box (preserveAspectRatio="none"),
   which is fine for invented land and would NOT be fine for a real
   coastline. Strokes are pinned to device pixels so the stretch does
   not thicken one axis. */
.atr__graticule {
  stroke: rgba(243, 240, 230, 0.07);
  stroke-width: 1;
  fill: none;
}
.atr__land {
  fill: rgba(243, 240, 230, 0.08);
  stroke: rgba(243, 240, 230, 0.16);
  stroke-width: 1;
}
.atr__journey {
  fill: none;
  stroke: var(--color-accent);
  stroke-width: 2;
  stroke-dasharray: 5 5;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.85;
}
.atr__journey[hidden] { display: none; }

/* --- Pins ------------------------------------------------- */

.atr__pins {
  position: absolute;
  inset: 0;
}
/* The hit box is EXACTLY 44px square and centered on the place, and the
   label floats out of flow beside it. Letting the label sit in flow was
   the first attempt and it pushed the dot off its own coordinate by half
   the length of the place name. */
.atr__pin {
  position: absolute;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
  border: 0;
  padding: 0;
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--color-text-light);
  font-family: var(--font-sans);
  font-size: 0.82rem;
  cursor: pointer;
}
.atr__pin:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}
.atr__pin[hidden] { display: none; }

/* The dot carries the location type; the count rides beside it, the
   way the product's marker carries its count badge. */
.atr__dot {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 18px;
  height: 18px;
  border-radius: var(--radius-full);
  background: var(--atr-type, var(--color-text-muted));
  box-shadow: 0 0 0 4px rgba(33, 53, 53, 0.55);
  transform: translate(-50%, -50%);
  transition: box-shadow var(--transition-fast), transform var(--transition-fast);
}
.atr__pin:hover .atr__dot { transform: translate(-50%, -50%) scale(1.15); }

/* Labels run right of the dot on the left half of the map and left of it
   on the right half, so a place name never runs off the plot and gets
   clipped by the rounded corner. */
.atr__label {
  position: absolute;
  top: 50%;
  left: 30px;
  transform: translateY(-50%);
  display: flex;
  align-items: baseline;
  gap: 6px;
  white-space: nowrap;
}
.atr__pin--flip .atr__label {
  left: auto;
  right: 30px;
  flex-direction: row-reverse;
}

/* Legend colors. The product's own legend is drawn from raw hex in
   atlas-map.js (LOCATION_COLORS). This page may not invent hex, so
   each type maps onto the nearest marketing token: the same ordering
   and the same five names, in the palette this surface owns. */
.atr__dot--birthplace { --atr-type: var(--color-accent); }
.atr__dot--residence  { --atr-type: var(--color-sky); }
.atr__dot--school     { --atr-type: var(--color-sage); }
.atr__dot--work       { --atr-type: var(--color-accent-hover); }
.atr__dot--visited    { --atr-type: var(--color-text-muted); }
.atr__dot--photos     { --atr-type: var(--color-surface); }

/* A group with nothing human behind it. Dashed ring in the product,
   dashed ring here. The type color rides the ring rather than being
   dropped: on a sample where most pins are estimates, filling only the
   confirmed ones would leave two thirds of the legend unexplained. */
.atr__pin--estimate .atr__dot {
  background: transparent;
  border: 2px dashed var(--atr-type, var(--color-surface));
  box-shadow: 0 0 0 4px rgba(33, 53, 53, 0.55);
  animation: atr-breathe 3.2s ease-in-out infinite;
}
@keyframes atr-breathe {
  0%, 100% { opacity: 0.55; }
  50%      { opacity: 1; }
}

.atr__count {
  font-variant-numeric: tabular-nums;
  color: var(--color-text-light);
  text-shadow: 0 1px 3px rgba(33, 53, 53, 0.9);
}
.atr__pin-name {
  color: var(--color-text-light);
  text-shadow: 0 1px 3px rgba(33, 53, 53, 0.9);
}
.atr__pin--on .atr__dot,
.atr__pin--estimate.atr__pin--on .atr__dot {
  box-shadow: 0 0 0 4px rgba(33, 53, 53, 0.55), 0 0 0 7px var(--color-accent);
}

/* Below the wide breakpoint the names would sit on top of one another,
   so the map keeps the dots and the panel does the naming. Every pin
   still carries its full place name in aria-label, so a screen reader
   loses nothing at any width. */
@media (max-width: 719px) {
  /* Taller, not squarer. The places sit on seven horizontal bands, and a
     square plot on a 390px phone puts those bands 34px apart while every
     hit box is 44px, so vertically adjacent pins would overlap and eat
     each other's taps. 3:4 spreads them past the target size. */
  .atr__plot { aspect-ratio: 3 / 4; }
  .atr__pin-name { display: none; }
}

/* --- The pin panel (mirrors the popup) --------------------- */

.atr__detail {
  background: rgba(243, 240, 230, 0.06);
  border-radius: var(--radius-md);
  padding: var(--space-sm);
  min-height: 9.5rem;
}
.atr__place {
  font-family: var(--font-serif);
  font-size: 1.15rem;
  line-height: 1.3;
  color: var(--color-text-light);
  margin: 0 0 var(--space-xs);
}
.atr__meta {
  font-family: var(--font-sans);
  font-size: 0.9rem;
  color: var(--color-accent);
  margin: 0 0 var(--space-xs);
}
.atr__people {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
  margin: 0 0 var(--space-xs);
}
.atr__chip {
  font-family: var(--font-sans);
  font-size: 0.82rem;
  padding: 4px 10px;
  border-radius: var(--radius-full);
  background: rgba(243, 240, 230, 0.12);
  color: var(--color-text-light);
}
.atr__more {
  font-family: var(--font-sans);
  font-size: 0.82rem;
  padding: 4px 2px;
  color: var(--color-text-muted);
}
.atr__range,
.atr__source {
  font-family: var(--font-sans);
  font-size: 0.88rem;
  line-height: 1.55;
  color: var(--color-text-muted);
  margin: 0 0 var(--space-xs);
}
/* The drawn stand-in for the product's map-pin emoji. Emoji are banned on
   customer surfaces, and this replica is all hand-drawn SVG anyway. */
.atr__source {
  display: flex;
  align-items: flex-start;
  gap: 6px;
}
.atr__pin-mark {
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
  margin-top: 0.2em;
}
.atr__range:last-child,
.atr__source:last-child { margin-bottom: 0; }

/* --- Legend ------------------------------------------------ */

.atr__legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs) var(--space-md);
  margin: 0;
  padding: 0;
  list-style: none;
}
.atr__legend li {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  font-family: var(--font-sans);
  font-size: 0.82rem;
  color: var(--color-text-muted);
}
/* The pin dot is absolutely positioned inside its 44px hit box. Reused in
   the legend it would escape the <li> and position against the replica
   panel instead, which is how the first pass shipped a legend of labels
   with no swatches at all. Put it back in flow here. */
.atr__legend .atr__dot {
  position: static;
  transform: none;
  flex: 0 0 auto;
  width: 12px;
  height: 12px;
  box-shadow: none;
  animation: none;
}
.atr__legend-title {
  font-family: var(--font-sans);
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-accent);
  margin: 0 0 var(--space-xs);
}

/* Anyone who has asked for less motion gets the same map, the same pins
   and the same dashed rings, with nothing breathing or growing under
   them. No information lives in the motion, so nothing is lost. */
@media (prefers-reduced-motion: reduce) {
  .atr__dot { transition: none; }
  /* Matched selector, not a bare `.atr__dot`: the breathing rule is
     `.atr__pin--estimate .atr__dot`, and the shorter selector loses on
     specificity, which is how this shipped still animating the first time. */
  .atr__pin--estimate .atr__dot {
    animation: none;
    opacity: 1;
  }
  .atr__pin:hover .atr__dot { transform: translate(-50%, -50%); }
}
