/* The map tab of the directory.
 *
 * Two columns that become one: the country on the left, the same numbers as a
 * ranked list on the right. The list is not a legend for the map - it is the
 * map's accessible twin, and on a phone it is the whole thing worth reading.
 *
 * Every animation here is entrance or hover. Nothing loops except the marker
 * halo, which is what makes a busy region catch the eye, and all of it stops
 * under prefers-reduced-motion. */

.sellermap {
  display: grid;
  /* The country is far taller than it is wide, so the map column is sized to
     what the drawing actually needs. Given a free 1fr it stretched to the width
     of the page and left the map as a thin strip down the middle of an empty
     card. */
  grid-template-columns: auto minmax(0, 26rem);
  gap: clamp(1rem, 3vw, 2.25rem);
  align-items: start;
  justify-content: center;
}

/* ---- the country ------------------------------------------------------- */

.sellermap-frame {
  position: relative;
  /* Hugs the map rather than the column. */
  width: fit-content;
  max-width: 100%;
  margin-inline: auto;
  background: var(--surface);
  border: 1px solid var(--pink-line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: clamp(.5rem, 2vw, 1.25rem);
  overflow: hidden;
}

/* A slow drift across the card, behind the sea. Cheap - one transform on one
   pseudo-element - and it stops the large pale area reading as a dead zone. */
.sellermap-frame::before {
  content: '';
  position: absolute;
  inset: -40%;
  background:
    radial-gradient(46% 38% at 28% 20%, rgba(254, 81, 130, .07), transparent 72%),
    radial-gradient(42% 36% at 76% 70%, rgba(126, 92, 200, .06), transparent 72%);
  animation: sellermapDrift 26s var(--ease) infinite alternate;
  pointer-events: none;
}

@keyframes sellermapDrift {
  from { transform: translate3d(-2%, -1%, 0) scale(1); }
  to   { transform: translate3d(2%, 1.5%, 0) scale(1.06); }
}

.sellermap-svg {
  display: block;
  /* Driven by height, not width: this is the one dimension the layout has to
     spare, and the aspect ratio picks the width from it. */
  height: min(76vh, 44rem);
  width: auto;
  max-width: 100%;
  position: relative;
}

/* ---- regions ----------------------------------------------------------- */

.sellermap-region {
  cursor: pointer;
  /* The lift on hover is a transform on the group, so it has to scale about the
     shape rather than the viewBox origin or every region flies to the corner. */
  transform-box: fill-box;
  transform-origin: center;
  transition: transform .35s var(--ease), filter .35s var(--ease);
}

.sellermap-land {
  fill: #efe7f4;
  stroke: #fff;
  stroke-width: 1.6;
  stroke-linejoin: round;
  transition: fill .3s var(--ease);
}

/* Five steps of the brand pink, lightest to full. Deliberately not a hue ramp:
   one colour getting stronger reads as "more of the same thing", which is what
   the number is, where a rainbow reads as different kinds of thing. */
.sellermap-region.is-step-1 .sellermap-land { fill: #ffe7ef; }
.sellermap-region.is-step-2 .sellermap-land { fill: #ffc9dc; }
.sellermap-region.is-step-3 .sellermap-land { fill: #ffa3c1; }
.sellermap-region.is-step-4 .sellermap-land { fill: #ff789f; }
.sellermap-region.is-step-5 .sellermap-land { fill: var(--pink); }

.sellermap-region.is-empty .sellermap-land { fill: #ece4f2; }

.sellermap-region:hover,
.sellermap-region:focus-visible,
.sellermap-region.is-lit {
  transform: translateY(-3px) scale(1.012);
  filter: url(#sellermapLift);
  outline: none;
}

.sellermap-region:hover .sellermap-land,
.sellermap-region:focus-visible .sellermap-land,
.sellermap-region.is-lit .sellermap-land {
  fill: var(--pink-deep);
}

.sellermap-region.is-empty:hover .sellermap-land,
.sellermap-region.is-empty.is-lit .sellermap-land {
  fill: #d9cee2;
}

/* Keyboard focus needs to be visible on the shape itself: the filter lift alone
   is too subtle to serve as a focus ring. */
.sellermap-region:focus-visible .sellermap-land {
  stroke: var(--ink);
  stroke-width: 3;
}

/* ---- markers ----------------------------------------------------------- */

/* Above every region's land, and transparent to the pointer: the click belongs
   to the region underneath. */
.sellermap-pins { pointer-events: none; }
.sellermap-pin { pointer-events: none; }

.sellermap-dot {
  fill: #fff;
  stroke: var(--pink-deep);
  stroke-width: 3;
  transition: transform .3s var(--ease);
  transform-box: fill-box;
  transform-origin: center;
}

.sellermap-num {
  fill: var(--pink-deep);
  font-weight: 800;
  text-anchor: middle;
  font-family: inherit;
  letter-spacing: -.02em;
}

.sellermap-pin.is-lit .sellermap-dot { transform: scale(1.16); }
.sellermap-pin.is-lit .sellermap-num { fill: var(--pink-deep); }

/* The halo is the only looping animation on the page. Two of them, half a cycle
   apart, so the pulse is continuous rather than a beat with a gap in it. */
.sellermap-halo {
  fill: var(--pink);
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
  animation: sellermapPulse 3.4s var(--ease) infinite;
  animation-delay: var(--sellermap-delay, 0s);
}

.sellermap-halo-2 { animation-delay: calc(var(--sellermap-delay, 0s) + 1.7s); }

@keyframes sellermapPulse {
  0%   { opacity: .38; transform: scale(1); }
  70%  { opacity: 0;   transform: scale(2.5); }
  100% { opacity: 0;   transform: scale(2.5); }
}

/* ---- entrance ---------------------------------------------------------- */

/* The country assembles densest-region-first, which is the order the markup is
   in. Applied only once the script marks the map ready, so a slow parse never
   leaves half a country visible mid-animation. */
[data-sellermap].is-ready .sellermap-region {
  animation: sellermapRise .7s var(--ease) both;
  animation-delay: var(--sellermap-delay, 0s);
}

@keyframes sellermapRise {
  from { opacity: 0; transform: translateY(14px) scale(.985); }
  to   { opacity: 1; transform: none; }
}

[data-sellermap].is-ready .sellermap-pin {
  animation: sellermapDrop .6s cubic-bezier(.2, 1.5, .4, 1) both;
  /* Lands after its own region has arrived. */
  animation-delay: calc(var(--sellermap-delay, 0s) + .38s);
}

@keyframes sellermapDrop {
  from { opacity: 0; transform: translateY(-22px) scale(.4); }
  to   { opacity: 1; }
}

/* ---- the hover card ---------------------------------------------------- */

.sellermap-card {
  position: absolute;
  z-index: 4;
  min-width: 11rem;
  max-width: 15rem;
  padding: .7rem .85rem;
  background: var(--surface-solid);
  border: 1px solid var(--pink-line);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  pointer-events: none;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity .18s var(--ease), transform .18s var(--ease);
}

.sellermap-card.is-on { opacity: 1; transform: none; }

.sellermap-card p { margin: 0; }
.sellermap-card-name { font-weight: 800; color: var(--ink); line-height: 1.25; }
.sellermap-card-count { color: var(--pink-deep); font-weight: 700; font-size: .92rem; margin-top: .15rem !important; }
.sellermap-card-ranks { color: var(--muted); font-size: .82rem; margin-top: .2rem !important; line-height: 1.35; }
.sellermap-card-ranks:empty { display: none; }
.sellermap-card-go { color: var(--muted); font-size: .78rem; margin-top: .4rem !important; }

/* ---- the side panel ---------------------------------------------------- */

.sellermap-side { display: grid; gap: 1rem; }

.sellermap-totals {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: .6rem;
}

.sellermap-total {
  background: var(--surface);
  border: 1px solid var(--pink-line);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
  padding: .7rem .5rem;
  text-align: center;
}

.sellermap-total-n {
  display: block;
  font-size: 1.5rem;
  font-weight: 800;
  color: var(--pink-deep);
  line-height: 1.1;
}

.sellermap-total-l {
  display: block;
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--muted);
  margin-top: .2rem;
}

.sellermap-overseas {
  display: flex;
  align-items: center;
  gap: .55rem;
  padding: .7rem .85rem;
  background: var(--surface);
  border: 1px solid var(--pink-line);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
  color: var(--ink-soft);
  font-size: .88rem;
  text-decoration: none;
  transition: box-shadow .25s var(--ease), transform .25s var(--ease);
}

.sellermap-overseas:hover { transform: translateY(-1px); box-shadow: var(--shadow); }
.sellermap-overseas-ico { width: 1.15rem; height: 1.15rem; flex: none; color: var(--pink); }

.sellermap-list-head {
  margin: .25rem 0 0;
  font-size: .78rem;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--muted);
  font-weight: 700;
}

.sellermap-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: .25rem;
  /* Seventeen rows is taller than the map on a wide screen; scrolling the list
     rather than the page keeps the two side by side. */
  /* Ends level with the map: the two are read together, and a list that stops
     a third of the way down looks truncated rather than scrollable. */
  max-height: min(52vh, 33rem);
  overflow-y: auto;
  padding-right: .25rem;
  /* A row cut off mid-height by the scroll box looks like a bug; faded, it
     reads as the list continuing. */
  mask-image: linear-gradient(to bottom, #000 calc(100% - 1.6rem), transparent);
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 1.6rem), transparent);
}

.sellermap-row a {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: .5rem;
  padding: .45rem .6rem;
  border-radius: var(--radius-sm);
  text-decoration: none;
  color: var(--ink);
  overflow: hidden;
  transition: background .2s var(--ease);
}

/* The bar is behind the text rather than beside it: at seventeen rows a
   separate bar column costs more width than the names can spare. */
.sellermap-row-bar {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--sellermap-pct, 0%);
  background: linear-gradient(90deg, rgba(254, 81, 130, .20), rgba(254, 81, 130, .07));
  border-radius: inherit;
  transform-origin: left center;
  transition: filter .2s var(--ease);
}

[data-sellermap].is-ready .sellermap-row-bar {
  animation: sellermapBar .8s var(--ease) both;
  animation-delay: .25s;
}

@keyframes sellermapBar {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

.sellermap-row-name { position: relative; min-width: 0; }
.sellermap-row-name b { display: block; font-size: .92rem; font-weight: 700; }
.sellermap-row-name em {
  display: block;
  font-style: normal;
  font-size: .74rem;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sellermap-row-n {
  position: relative;
  font-weight: 800;
  color: var(--pink-deep);
  font-variant-numeric: tabular-nums;
}

.sellermap-row.is-empty .sellermap-row-name b { color: var(--muted); font-weight: 600; }
.sellermap-row.is-empty .sellermap-row-n { color: var(--muted); font-weight: 600; }

.sellermap-row a:hover,
.sellermap-row a:focus-visible,
.sellermap-row.is-lit a { background: var(--pink-wash); outline: none; }
.sellermap-row a:focus-visible { box-shadow: var(--ring); }

.sellermap-credit {
  margin: 0;
  font-size: .72rem;
  line-height: 1.5;
  color: var(--muted);
}

/* ---- narrow ------------------------------------------------------------ */

@media (max-width: 60rem) {
  .sellermap { grid-template-columns: minmax(0, 1fr); }
  .sellermap-svg { height: auto; width: 100%; max-height: 68vh; }
  /* The list stops being a sidebar and becomes the rest of the page, so it
     should run its full length rather than scroll inside itself - and with no
     scroll there is nothing for the fade to hint at. */
  .sellermap-list {
    max-height: none;
    overflow: visible;
    mask-image: none;
    -webkit-mask-image: none;
  }
}

/* ---- the chip the map hands the list ----------------------------------- */

.directory-region-chip {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  margin: .75rem 0 0;
  padding: .35rem .5rem .35rem .6rem;
  background: var(--pink-wash);
  border: 1px solid var(--pink-line);
  border-radius: 999px;
  font-size: .88rem;
  font-weight: 600;
  color: var(--ink);
}

.directory-region-ico { width: 1rem; height: 1rem; color: var(--pink); flex: none; }

.directory-region-chip a {
  display: grid;
  place-items: center;
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 50%;
  color: var(--muted);
  text-decoration: none;
  font-size: 1rem;
  line-height: 1;
  transition: background .2s var(--ease), color .2s var(--ease);
}

.directory-region-chip a:hover { background: var(--pink); color: #fff; }

.directory-region-back { margin: .4rem 0 0; font-size: .85rem; }
.directory-region-back a { color: var(--muted); text-decoration: none; }
.directory-region-back a:hover { color: var(--pink-deep); text-decoration: underline; }

/* ---- reduced motion ---------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  /* Everything lands where it was going, immediately. The halo is removed
     rather than paused: a pulse frozen mid-expansion is a grey ring around
     every marker that looks like a rendering fault. */
  .sellermap-frame::before,
  [data-sellermap].is-ready .sellermap-region,
  [data-sellermap].is-ready .sellermap-pin,
  [data-sellermap].is-ready .sellermap-row-bar {
    animation: none;
  }
  .sellermap-halo { display: none; }
  .sellermap-region,
  .sellermap-dot,
  .sellermap-card,
  .sellermap-overseas { transition: none; }
}
