:root {
  --live: #d92d20;
  --finished: #344054;
  --scheduled: #1570ef;
  --card: #ffffff;
  --ink: #101828;
  --muted: #667085;
  --line: rgba(16, 24, 40, .12);
  --shadow: 0 1px 2px rgba(16, 24, 40, .1), 0 6px 16px rgba(16, 24, 40, .16);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

* { box-sizing: border-box; }

html, body { height: 100%; margin: 0; }

#map { position: absolute; inset: 0; }

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

   Three frames, not one: what the map holds (stats), when (date) and where
   (country). Each is its own card, stacked down the left.

   Sizes here are fought over by specificity: `#panel button` outranks any
   plain class, so every component rule that sets a font or a border has to be
   written `#panel .thing` to survive. That is why the panel is 272 wide --
   the status row needs 230 of it, and the numbers have to fit.             */

#panel {
  position: absolute;
  top: 16px;
  left: 16px;
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: min(272px, calc(100vw - 32px));
  max-height: calc(100vh - 32px);
}

.frame {
  flex: none;
  padding: 12px 14px;
  background: var(--card);
  border-radius: 12px;
  box-shadow: var(--shadow);
}

#panel h1 { margin: 0; font-size: 15px; letter-spacing: .02em; color: var(--ink); }

summary.frame-title {
  display: flex;
  align-items: center;
  margin: 0 0 8px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
  cursor: pointer;
  list-style: none;          /* Firefox */
}

summary.frame-title::-webkit-details-marker { display: none; }

/* Closed, the title is the whole card, so it should not hold space for content
   that is not there. */
details:not([open]) > summary.frame-title { margin-bottom: 0; }

/* One chevron for both kinds of summary: the frame titles and the country rows. */
summary.frame-title::after,
summary.country::after {
  content: "";
  width: 5px;
  height: 5px;
  margin-left: auto;
  border-right: 1.5px solid #98a2b3;
  border-bottom: 1.5px solid #98a2b3;
  transform: translateY(-2px) rotate(45deg);
}

details[open] > summary.frame-title::after,
details[open] > summary.country::after { transform: translateY(1px) rotate(-135deg); }

#stats .line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin-top: 4px;
}

#summary { margin: 0; font-size: 12.5px; color: var(--muted); white-space: nowrap; }

/* --------------------------------------------------------------- filters

   Every button carries the count it would give. Zero and unpressed means there
   is nothing behind it, so the button goes flat.                            */

#panel button {
  border: 0;
  background: none;
  font-family: inherit;
  font-size: 11.5px;
  color: var(--ink);
  cursor: pointer;
}

#panel button:disabled { color: #98a2b3; cursor: default; }

/* :hover outranks .on unless the selected state is excluded here, and a chosen
   filter must not go pale under the cursor. */
#panel button:not(:disabled):not(.on):hover { background: rgba(16, 24, 40, .05); }

/* One selected look for all three filters, borrowing none of the status
   colours -- those mean something else. */
#panel button.on { background: var(--ink); color: #fff; }

.n {
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}

.on .n { color: rgba(255, 255, 255, .7); }
#panel button:disabled .n { color: #cfd4dc; }

#panel #reset {
  flex: none;
  padding: 2px 7px;
  border: 1px solid var(--line);
  border-radius: 7px;
  font-size: 10.5px;
  color: var(--muted);
}

/* The legend, which is also the status filter. Spread across the frame rather
   than packed left: three items of very different widths look accidental
   otherwise. */
/* The `hidden` attribute is only `display: none` in the browser's own
   stylesheet, so ANY author `display` rule beats it -- and #legend, #modes and
   .leagues all set one. Without this, hiding the status filter in clubs mode did
   nothing at all and the panel showed 565 finished *games* over a map of clubs.
   The same family as the specificity trap in **The panel**: a rule that looks
   unrelated silently wins. */
[hidden] { display: none !important; }

#legend {
  display: flex;
  justify-content: space-between;
  gap: 2px;
  margin-top: 9px;
}

#panel .status {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px 5px;
  border-radius: 8px;
  font-size: 11px;
  color: var(--muted);
}

.swatch { width: 9px; height: 9px; border-radius: 50%; display: inline-block; flex: none; }
.swatch.live      { background: var(--live); }
.swatch.finished  { background: var(--finished); }
.swatch.scheduled { background: var(--scheduled); }

/* Equal thirds: the three days are the same kind of thing, so they get the
   same room whatever their names are. */
.chips { display: flex; gap: 4px; margin-bottom: 8px; }

#panel .chip {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 4px 2px;
  border-radius: 8px;
  font-size: 11px;
}

#panel #day {
  width: 100%;
  padding: 5px 7px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: none;
  color: var(--ink);
  font-family: inherit;
  font-size: 11.5px;
}

/* ----------------------------------------------------------- the table

   The chosen competition's standings. A list rather than a <table>: there are
   five columns of fixed shape and no header worth 244px of panel, and a grid
   lines them up without the markup a real table would need.

   Written `#panel .standing ...` throughout for the same reason everything else
   here is: `#panel button` outranks any plain class selector, so a bare
   `.standing button { font-size }` loses to `font: inherit` and the rows come
   out at 16px in a panel built for 11. */
#table {
  /* Twenty rows is taller than a laptop window has to spare below the country
     list, so this scrolls on the same terms -- and against the viewport too, for
     a phone held sideways. */
  max-height: min(300px, 45vh);
  overflow-y: auto;
  margin: 0;
  padding: 0;
  list-style: none;
}

#panel .standing { border-top: 1px solid var(--line); }
#panel .standing:first-child { border-top: none; }

/* One grid for both kinds of row -- the clickable and the inert -- so a club we
   cannot place still lines up with the rest of the column. */
#panel .standing > button,
#panel .standing > .unplaced {
  display: grid;
  grid-template-columns: 18px 1fr 16px 34px 22px;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 4px 6px 4px 0;
  border: 0;
  border-left: 3px solid transparent;
  background: none;
  color: var(--ink);
  font-family: inherit;
  font-size: 11px;
  text-align: left;
}

#panel .standing > button { cursor: pointer; }
#panel .standing > button:hover { background: rgba(16, 24, 40, .05); }

/* A club we do not carry: in the table, because a table missing a row is
   simply wrong, but with no pin behind it to go to. */
#panel .standing > .unplaced { color: var(--muted); }

#panel .standing .pos { color: var(--muted); text-align: right; font-variant-numeric: tabular-nums; }
#panel .standing .club {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#panel .standing .played,
#panel .standing .goals {
  color: var(--muted);
  text-align: right;
  font-variant-numeric: tabular-nums;
}
#panel .standing .pts {
  text-align: right;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* The zone stripe. Two families, which is all the feed's codes come in: `q`
   is promotion or qualification, `r` is relegation. Our colours, not the
   source's -- the classification is a fact about the league, the palette is
   somebody's design. The name is on the row's title attribute. */
#panel .zone-up   > button, #panel .zone-up   > .unplaced { border-left-color: #12b76a; }
#panel .zone-down > button, #panel .zone-down > .unplaced { border-left-color: var(--live); }

/* ------------------------------------------------------------- countries */

/* The country list is the one part long enough to outgrow the window, so it is
   the one that scrolls -- capped against the viewport as well as in pixels, for
   a phone held sideways. */
#countries {
  max-height: min(268px, 45vh);
  overflow-y: auto;
}

#countries > details + details { border-top: 1px solid var(--line); }

summary.country {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 4px;
  font-size: 12px;
  color: var(--ink);
  cursor: pointer;
  list-style: none;          /* Firefox */
}

summary.country::-webkit-details-marker { display: none; }
summary.country:hover { background: rgba(16, 24, 40, .04); border-radius: 7px; }
summary.country .label { flex: 1; }

/* A fixed slot so the country names line up, whatever shape the flag is: real
   ratios run from 2:1 (Ireland) to square (Switzerland). The image is sized by
   its two maxima, so it scales to fit without being stretched or cropped. */
summary.country .flag {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 14px;
}

summary.country .flag img {
  width: auto;
  height: auto;
  max-width: 22px;
  max-height: 14px;
  border-radius: 1.5px;
  /* England's flag is white to the edges and would have none against the card. */
  box-shadow: 0 0 0 .5px rgba(16, 24, 40, .25);
}

.leagues {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 2px 0 6px 22px;
}

#panel .league {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 7px;
  border-radius: 7px;
  font-size: 11.5px;
  text-align: left;
}

#panel .league .label { flex: 1; }

#error {
  position: absolute;
  z-index: 3;
  top: 16px;
  left: 50%;
  transform: translateX(-50%);
  margin: 0;
  padding: 10px 14px;
  border-radius: 10px;
  background: #fef3f2;
  color: #b42318;
  border: 1px solid #fda29b;
  font-size: 13px;
  box-shadow: var(--shadow);
}

/* ----------------------------------------------------------------- pins

   Never set `position` on .marker: MapLibre positions the marker element
   itself via .maplibregl-marker, and overriding it drops every pin out of
   absolute positioning and into normal document flow.                     */

.marker { line-height: 0; }
.marker:hover { z-index: 10; }
.marker.pinned { z-index: 11; }

/* The context the card and the clock badge hang off. It has to be an inner
   element, never .marker itself. */
.pin-wrap { position: relative; display: inline-block; line-height: 0; }

.pin {
  position: relative;          /* anchor for the clock badge */
  display: inline-block;
  padding: 3px 7px;
  border-radius: 11px;
  background: var(--finished);
  color: #fff;
  font-size: 11.5px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  line-height: 1.25;
  white-space: nowrap;
  box-shadow: var(--shadow);
  cursor: pointer;
  transition: transform .12s ease;
}

.marker:hover .pin,
.marker.pinned .pin { transform: scale(1.12); }

.live .pin { background: var(--live); }

.scheduled .pin {
  background: var(--card);
  color: var(--scheduled);
  border: 1px solid var(--scheduled);
  font-weight: 600;
}

/* Live clock: small, tucked into the pin's top-right corner. */
.minute {
  position: absolute;
  top: -8px;
  right: -10px;
  padding: 0 4px;
  border-radius: 8px;
  background: var(--ink);
  color: #fff;
  font-size: 9px;
  font-weight: 700;
  line-height: 14px;
  box-shadow: 0 1px 3px rgba(16, 24, 40, .35);
}

.minute::after {
  content: "";
  display: inline-block;
  width: 3.5px;
  height: 3.5px;
  margin-left: 3px;
  border-radius: 50%;
  background: #fc7a72;
  vertical-align: middle;
  animation: blink 1.4s infinite;
}

@keyframes blink { 50% { opacity: .2; } }

@media (prefers-reduced-motion: reduce) { .minute::after { animation: none; } }

/* ------------------------------------------------------------------ card

   Shown on hover, kept on a click (.pinned, set from JS). The same box holds
   a single game or a cluster's list, so the padding lives on the content and
   not here -- a list has to reach the card's edges.                        */

.card {
  position: absolute;
  bottom: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  width: 258px;
  /* Never wider than the screen. The card is centred on its pin, so near an edge
     it still hangs off one side -- the sheet rule at the end of this file is what
     actually solves that, and this is the belt for the case a desktop window is
     narrow but not narrow enough to trigger it. */
  max-width: calc(100vw - 24px);
  background: var(--card);
  color: var(--ink);
  border-radius: 10px;
  box-shadow: var(--shadow);
  font-size: 12.5px;
  font-weight: 400;
  line-height: 1.4;
  white-space: normal;
  text-align: left;
  opacity: 0;
  visibility: hidden;          /* also switches pointer events off */
  transition: opacity .12s ease, transform .12s ease;
}

.marker:hover .card,
.marker.pinned .card {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0);
}

/* The 10px between card and pin would break the hover the moment the cursor
   crossed it, which makes a list impossible to reach. This bridges the gap
   without being visible; it only exists while the card does. */
.card::before {
  content: "";
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  height: 11px;
}

.card-body { padding: 10px 12px; }

/* Little arrow pointing back down at the pin. */
.card::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  margin-left: -6px;
  border: 6px solid transparent;
  border-top-color: var(--card);
}

.card .meta {
  margin: 0 0 7px;
  font-size: 10.5px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
}

.card .row {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  align-items: baseline;
}

.card .team { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.card .goals { font-variant-numeric: tabular-nums; font-weight: 700; }
.card .row.lost .team, .card .row.lost .goals { color: var(--muted); font-weight: 400; }

.card .when {
  margin-top: 7px;
  padding-top: 6px;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 11.5px;
}

.card .where { color: var(--muted); font-size: 11.5px; }

/* -------------------------------------------------------------- clusters

   A cluster stands in for pins that cannot be told apart at this zoom: a
   count inside a ring, the ring split by the statuses it hides.           */

.cluster-pin {
  position: relative;          /* the ring's inner disc hangs off this */
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  box-shadow: var(--shadow);
  cursor: pointer;
  font: inherit;
  transition: transform .12s ease;
}

.cluster-pin::before {
  content: "";
  position: absolute;
  inset: 3.5px;
  border-radius: 50%;
  background: var(--card);
}

.cluster-pin:hover,
.marker.pinned .cluster-pin { transform: scale(1.12); }
.cluster-pin:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

.cluster-pin .count {
  position: relative;          /* above the inner disc */
  color: var(--ink);
  font-size: 12px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

/* ------------------------------------------------------------ the list */

.cluster .card { width: 272px; }

.cluster-head {
  margin: 0;
  padding: 9px 12px;
  border-radius: 10px 10px 0 0;
  border-bottom: 1px solid var(--line);
  color: var(--ink);
  font-size: 12.5px;
  font-weight: 650;
}

.cluster-head span {
  display: block;
  margin-top: 1px;
  color: var(--muted);
  font-size: 11px;
  font-weight: 400;
}

.entries { max-height: 262px; overflow-y: auto; }

.entry {
  display: grid;
  grid-template-columns: 42px 1fr;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 7px 12px;
  border: 0;
  border-top: 1px solid var(--line);
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.entry:first-child { border-top: 0; }
/* No overflow clipping on the card -- it would cut off the arrow and the
   hover bridge -- so the last row rounds its own corners. */
.entry:last-child { border-radius: 0 0 10px 10px; }
.entry:hover { background: rgba(16, 24, 40, .04); }
.entry:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }

.entry-badge {
  padding: 2px 0;
  border-radius: 9px;
  background: var(--finished);
  color: #fff;
  font-size: 11px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  text-align: center;
}

.entry.live .entry-badge { background: var(--live); }

.entry.scheduled .entry-badge {
  background: var(--card);
  color: var(--scheduled);
  border: 1px solid var(--scheduled);
  padding: 1px 0;
  font-weight: 600;
}

.entry-body { min-width: 0; }

.entry-teams,
.entry-where {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.entry-teams { color: var(--ink); font-size: 12.5px; }
.entry-teams i { color: var(--muted); font-style: normal; font-size: 11px; }
.entry-where { margin-top: 1px; color: var(--muted); font-size: 11px; }

/* ------------------------------------------------------- the clubs mode */

/* Two buttons, not a fourth filter: they change what the map is about. Written
   `#panel .mode` for the same reason every component rule here is -- `#panel
   button` outranks any plain class selector, so a bare `.mode { font-size }`
   loses to `font: inherit` and renders at 16px in an 11px panel. */
#panel #modes {
  display: flex;
  gap: 4px;
  margin-top: 8px;
}

#panel .mode {
  flex: 1;
  padding: 4px 0;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: var(--card);
  color: var(--muted);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .02em;
  text-transform: lowercase;
  cursor: pointer;
}

/* :not(.on):hover, so the chosen mode does not go pale under the cursor. */
#panel .mode:not(.on):hover { color: var(--ink); border-color: var(--ink); }

#panel .mode.on {
  background: var(--ink);
  border-color: var(--ink);
  color: #fff;
}

/* A club's pin is its crest, on a white disc so a crest with a transparent
   background still reads against the map. Square, unlike a game's pill: a crest
   has its own aspect ratio and is bounded rather than sized outright, exactly as
   the flags are -- real ones run from tall shields to wide banners. */
.crest {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--card);
  box-shadow: var(--shadow);
  cursor: pointer;
  transition: transform .12s ease;
}

.crest img {
  max-width: 22px;
  max-height: 22px;
  width: auto;
  height: auto;
}

.marker:hover .crest,
.marker.pinned .crest { transform: scale(1.12); }

/* No crest: initials rather than an empty disc. A nameless dot on a map is
   worse than a rough label. */
.crest .initials {
  color: var(--muted);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: 1;
}

/* The competitions on a club's card, as links out of this mode. */
.leagues {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 9px;
  padding-top: 9px;
  border-top: 1px solid var(--line);
}

.card .league-link {
  padding: 3px 7px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: var(--card);
  color: var(--ink);
  font: inherit;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
}

.card .league-link:hover { border-color: var(--ink); }
.card .league-link:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }

/* A club row in a shared-ground cluster: crest where a game shows its score. */
.entry.club .entry-crest {
  display: grid;
  place-items: center;
  height: 24px;
}

.entry.club .entry-crest img { max-width: 22px; max-height: 22px; }

.entry.club .entry-crest .initials {
  color: var(--muted);
  font-size: 10px;
  font-weight: 700;
}

/* --------------------------------------------------------- match reports

   Goals, the crowd, and the statistics behind a button. All three sit inside
   the same .card, which is why none of them may set a width: the card decides
   how wide it is, and on a phone that is the screen. */

/* Goals laid out as Flashscore lays them: the home side's reading from the left
   -- minute, score, scorer -- and the away side's mirrored from the right. The
   half of the row a goal sits in IS which team scored it, so nothing needs a
   label, and the eye can run down one edge to follow one team. */
.goals-list {
  margin-top: 8px;
  padding-top: 7px;
  border-top: 1px solid var(--line);
  display: grid;
  gap: 3px;
}

.goal {
  display: flex;
  align-items: baseline;
  gap: 5px;
  font-size: 11.5px;
  line-height: 1.35;
}

/* The mirror. `row-reverse` rather than a second set of rules, so the two halves
   can never drift apart. */
.goal.away { flex-direction: row-reverse; text-align: right; }

.goal .g-min {
  min-width: 26px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  font-size: 11px;
}
.goal.away .g-min { text-align: right; }

.goal .g-score {
  padding: 0 4px;
  border: 1px solid var(--line);
  border-radius: 5px;
  color: var(--ink);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.goal .g-mark { font-size: 10px; line-height: 1; }

.goal .g-kind {
  color: var(--muted);
  font-style: normal;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .02em;
}

/* The name is the part that has to give way when the card is narrow. */
.goal .g-who {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--ink);
  font-weight: 600;
}

.goal .g-who i { color: var(--muted); font-style: normal; font-weight: 400; }

/* Capacity above attendance: how many it holds, then how many came. */
.crowd {
  margin-top: 7px;
  padding-top: 6px;
  border-top: 1px solid var(--line);
  display: grid;
  gap: 2px;
  font-size: 11px;
}

.crowd-row { display: flex; justify-content: space-between; gap: 10px; }
.crowd-row span { color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.crowd-row b { font-variant-numeric: tabular-nums; }

/* The statistics: a button that grows the card, and forty rows behind it. Last
   in the card on purpose -- it is the only thing here that changes the card's
   height by a lot, and growing downwards from the bottom moves nothing above. */
.stats-block { border-top: 1px solid var(--line); }

/* `.card .stats-toggle`, not `.stats-toggle`: the panel's `#panel button` rule
   does not reach in here, but every other button in this file is qualified and
   an unqualified one is the next specificity accident waiting to happen. */
.card .stats-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  width: 100%;
  padding: 7px 12px;
  border: 0;
  border-radius: 0 0 10px 10px;
  background: none;
  color: var(--muted);
  font: inherit;
  font-size: 10.5px;
  font-weight: 650;
  letter-spacing: .04em;
  text-transform: uppercase;
  text-align: left;
  cursor: pointer;
}

.card .stats-toggle b {
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  font-weight: 700;
}

.card .stats-toggle:hover { color: var(--ink); }
.card .stats-toggle:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
.card .stats-toggle .chev { font-size: 9px; }

/* Its own scroll, and its own wheel: forty rows are taller than any sensible
   card, and the wheel over them belongs to the list rather than to the map.

   The scrollbar is made permanent on purpose. macOS hides an overlay scrollbar
   until something scrolls, so a list of ten rows out of thirty-four looked
   exactly like a list of ten rows with the last one mis-clipped -- the cap was
   working and there was no way to tell. A track that is always there says
   "there is more" without a word. */
.stat-rows {
  max-height: 232px;
  overflow-y: auto;
  padding: 0 12px 9px;
  border-top: 1px solid var(--line);
  scrollbar-width: thin;                       /* Firefox */
  scrollbar-color: var(--muted) transparent;
  /* Reserved whether or not the bar is showing, so the rows do not shift by its
     width the moment it appears. */
  scrollbar-gutter: stable;
}

/* WebKit and Blink ignore scrollbar-color, and their overlay bar is the one that
   vanishes. Styling it at all is what makes it stay. */
/* Wide enough to grab. 8px with a 2px inset left a 4px thumb, which is a target
   for a mouse and not for a hand. */
.stat-rows::-webkit-scrollbar { width: 11px; }
.stat-rows::-webkit-scrollbar-track { background: transparent; }
.stat-rows::-webkit-scrollbar-thumb {
  background: var(--muted);
  border-radius: 6px;
  border: 3px solid var(--card);
}
.stat-rows::-webkit-scrollbar-thumb:hover { background: var(--ink); }

.stat-row {
  display: grid;
  grid-template-columns: 3.2em 1fr 3.2em;
  align-items: baseline;
  gap: 6px;
  padding: 3px 0;
  font-size: 11px;
}

.stat-row + .stat-row { border-top: 1px solid var(--line); }
.stat-row span { color: var(--muted); text-align: center; }
.stat-row b { font-variant-numeric: tabular-nums; }
.stat-row b:last-child { text-align: right; }

/* ------------------------------------------------------------ on a phone

   No hover on a touch screen, so a card is only ever reached by a tap -- which
   pins it. A pinned card anchored to its pin is the thing that breaks here: a
   pin near the left edge puts a 258px card half off the screen, and the
   statistics make it taller than the viewport as well.

   So under 640px a pinned card stops being a tooltip and becomes a sheet: fixed
   to the bottom of the screen, full width less a margin, and scrollable. The
   hover card is left exactly as it was, because on a phone it never appears. */
@media (max-width: 640px) {
  .marker.pinned .card {
    position: fixed;
    left: 12px;
    right: 12px;
    bottom: 12px;
    top: auto;
    width: auto;
    max-width: none;
    max-height: 70vh;
    overflow-y: auto;
    transform: none;
    z-index: 20;
  }

  /* The arrow points at a pin the sheet is no longer beside, and the bridge
     exists to cross a gap that is no longer there. */
  .marker.pinned .card::after,
  .marker.pinned .card::before { display: none; }

  /* The sheet scrolls as one thing; a second scroll inside it fights the first. */
  .marker.pinned .stat-rows { max-height: none; overflow-y: visible; }

  /* A cluster's list is the same story. */
  .marker.pinned .entries { max-height: none; }
}
