/* Stats page. Same rule as the shell: no colour, no duration, no radius that
 * is not a token. */

.phead {
  padding: var(--s-6) var(--s-6) var(--s-5);
  border-bottom: 1px solid var(--ln);
  position: relative; overflow: hidden;
  background: radial-gradient(560px circle at var(--mx, 50%) var(--my, 0%), var(--spot), transparent 62%);
}
.phead > * { position: relative; z-index: 2; }
.phead h1 { margin: 0 0 7px; font-size: var(--t-h2); }
.phead .sub { margin: 0; color: var(--mut); font-size: var(--t-sm); max-width: 58ch; }
.hint { color: var(--mut); font-size: var(--t-sm); max-width: 56ch; margin: 0 0 var(--s-4); }

/* stat strip */
.stats { display: grid; grid-template-columns: repeat(4, 1fr); border-top: 1px solid var(--ln); border-bottom: 1px solid var(--ln); }
.stat { padding: var(--s-5) var(--s-6); position: relative; transition: background-color var(--t-tint) ease; }
.stat::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 1px;
  background: var(--acc); box-shadow: 0 0 10px -1px var(--acc);
  transform: scaleX(0); transform-origin: center;
  transition: transform var(--t-move) var(--ease);
}
.stat:hover { background: var(--hov); }
.stat:hover::before { transform: scaleX(1); }
.stat + .stat { border-left: 1px solid var(--ln); }
.stat b { display: block; font-size: clamp(23px, 3.2vw, 32px); font-weight: 600; letter-spacing: -0.025em; margin-bottom: 1px; }
.stat span { color: var(--mut); }
@media (max-width: 700px) {
  .stats { grid-template-columns: repeat(2, 1fr); }
  .stat + .stat { border-left: 0; }
  .stat:nth-child(even) { border-left: 1px solid var(--ln); }
  .stat:nth-child(n+3) { border-top: 1px solid var(--ln); }
}

/* ── the weekly chart ───────────────────────────────────────────────────── */
.chart {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 5px;
  align-items: end; height: 210px; padding: var(--s-6) var(--s-6) 0;
}
.col { display: flex; flex-direction: column; justify-content: flex-end; height: 100%; position: relative; cursor: default; }
.col i {
  display: block; height: 0; border-radius: var(--rad-soft) var(--rad-soft) 0 0;
  background: var(--barbg);
  transition: height var(--t-grow) var(--ease), background-color var(--t-tint) ease, box-shadow var(--t-move) ease;
}
[data-seen="1"] .col i { height: var(--h); }
.col:hover i, .col:focus-visible i { background: var(--acc2); box-shadow: 0 0 18px -4px var(--acc2); }

/* The value sits in the flow directly above its own bar. Positioning it against
   the column put it at the top of the chart however short the bar was, which a
   screenshot showed plainly. Hidden with opacity, never display, so nothing
   reflows on hover. */
.col u {
  text-align: center; font-size: 10.5px; font-family: var(--mono); line-height: 1;
  color: var(--acc2); text-decoration: none; padding-bottom: 6px;
  opacity: 0; transform: translateY(4px);
  transition: opacity var(--t-tint) ease, transform var(--t-move) var(--ease);
}
.col:hover u, .col:focus-visible u { opacity: 1; transform: none; }
/* On a touch device this can never be revealed, and it was still costing width:
   the number is wider than a bar, so its min-content forced the column past the
   track and pushed the page 12px sideways at 320px. A label that cannot be shown
   should not be laid out. Keyboard focus still reveals it wherever hover exists. */
@media (hover: none) { .col u { display: none; } }

.xaxis {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 5px;
  padding: 9px var(--s-6) var(--s-6);
  font-size: 9.5px; font-family: var(--mono); color: var(--rank); text-align: center;
  border-bottom: 1px solid var(--ln);
}
/* Thirteen dates will not fit a phone, and overlapping labels are worse than
   half of them.
 *
 * The columns are `minmax(0, 1fr)` rather than `1fr` above, which is the part
 * that actually mattered: `1fr` is `minmax(auto, 1fr)`, and `auto` as a MINIMUM
 * is min-content. Each axis cell holds a date, so no column could shrink below
 * the width of "May", and thirteen of those plus gaps and padding measured 119px
 * wider than a 390px phone. The whole PAGE scrolled sideways as a result, which
 * is the one thing a layout must never do.
 *
 * Hiding every other label keeps the remaining ones from touching. Allowing the
 * track to shrink is what stops the page moving. */
@media (max-width: 700px) {
  .xaxis span:nth-child(even) { visibility: hidden; }
  /* Less side padding as well, so the bars get the width back rather than
     spending it on margins a phone cannot afford. */
  .chart { padding-inline: var(--s-4); }
  .xaxis { padding-inline: var(--s-4); }
}

/* ── ranked list ────────────────────────────────────────────────────────── */
.pane { padding: var(--s-6); }
.rname em { font-style: normal; display: block; font-size: var(--t-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.state { font-size: 11.5px; margin-top: 3px; display: inline-block; color: var(--mut); }
.state[data-s="working"] { color: var(--ok); }
.state[data-s="maintenance"] { color: var(--warn); }
.num { font-family: var(--mono); font-size: var(--t-sm); white-space: nowrap; color: var(--acc2); }
.art.none { display: grid; place-items: center; color: var(--rank); font-size: 15px; font-weight: 600; }

/* The ranking, two per line.
 *
 * It used to be the top ten in one column, which fitted. It is now every script
 * we have numbers for, and a single column turned that into a scroll rather than
 * a picture: the whole point of a ranking is seeing the shape of it at once.
 *
 * The rows keep their own bottom border, so the divider between the two columns
 * is the only thing added. `align-content: start` matters because a grid row
 * stretches to its tallest cell, and a script with a long name would otherwise
 * pad the one beside it. */
.ranking { display: grid; grid-template-columns: 1fr 1fr; align-content: start; }
.ranking .row:nth-child(odd) { border-right: 1px solid var(--ln); padding-right: var(--s-4); }
.ranking .row:nth-child(even) { padding-left: var(--s-4); }
/* `:last-child` cleared the final border when this was one column. In two
   columns the last TWO rows are on the bottom edge, and only one of them is the
   last child, which left a single hanging rule. */
.ranking .row:last-child, .ranking .row:nth-last-child(2):nth-child(odd) { border-bottom: 0; }

@media (max-width: 760px) {
  /* One column on a phone. Two columns of a name, a bar and a number inside
     360px is not a denser view, it is an unreadable one. */
  .ranking { grid-template-columns: 1fr; }
  .ranking .row:nth-child(odd) { border-right: 0; padding-right: var(--s-2); }
  .ranking .row:nth-child(even) { padding-left: var(--s-2); }
  .ranking .row:nth-last-child(2):nth-child(odd) { border-bottom: 1px solid var(--ln); }
}

/* ══ the redesign, 2026-08-01 ═══════════════════════════════════════════════
 *
 * The page opened with a heading, a paragraph, and then its figures, so the
 * first thing on a page whose entire subject is one number was not that number.
 * Below that sat sixty seven rows of identical shape, which is a list nobody
 * reads to the end, on data whose actual story is that a handful of games are
 * almost all of it.
 *
 * So: the total is the headline, the leaders get cards with their own thirteen
 * week line, and the long tail is the dense table it always should have been.
 * Same rule as everything else here, no colour, duration or radius that is not
 * a token.
 */

/* ── the headline ─────────────────────────────────────────────────────────── */
.sthero {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--s-8); align-items: end;
}
.sthero-copy { min-width: 0; }
.sthero-big { text-align: right; min-width: 0; }
.sthero-big b {
  display: block; font-weight: 600; letter-spacing: -0.03em; line-height: 1;
  font-size: clamp(38px, 7vw, 76px);
  font-variant-numeric: tabular-nums;
  color: var(--fg);
  text-shadow: 0 0 40px var(--bloom), 0 0 90px var(--bloom);
}
.sthero-big span {
  display: block; margin-top: var(--s-2);
  color: var(--mut); font-size: var(--t-xs);
  text-transform: uppercase; letter-spacing: var(--track-label);
}
@media (max-width: 760px) {
  .sthero { grid-template-columns: 1fr; align-items: start; gap: var(--s-5); }
  .sthero-big { text-align: left; }
}

/* How fresh the figures are, said out loud. A page of live numbers that does
   not say when it last heard from the server is asking to be trusted about
   something it has not mentioned. */
.stfresh {
  display: flex; align-items: center; gap: 7px;
  margin: var(--s-4) 0 0; color: var(--mut);
  font-size: var(--t-xs); font-family: var(--mono);
}
.stdot {
  width: 7px; height: 7px; flex: none; border-radius: var(--rad-pill);
  background: var(--ok); box-shadow: 0 0 9px -1px var(--ok);
  animation: gh-stat-pulse 2.4s var(--ease) infinite;
}
@keyframes gh-stat-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }
.stfresh[data-state="stale"] .stdot { background: var(--warn); box-shadow: 0 0 9px -1px var(--warn); animation: none; }
.stfresh[data-state="down"] .stdot { background: var(--rank); box-shadow: none; animation: none; }

/* Week on week, beside the week's figure. A number with no comparison is a
   number nobody can tell is good. */
.stdelta {
  display: block; margin-top: 5px;
  font-size: var(--t-xs); font-family: var(--mono); font-style: normal;
  font-variant-numeric: tabular-nums; color: var(--mut);
}
.stdelta[data-dir="up"] { color: var(--ok); }
.stdelta[data-dir="down"] { color: var(--warn); }
.stdelta:empty { display: none; }

/* ── the chart, given room ────────────────────────────────────────────────── */
.stchart-pane { padding-bottom: 0; }
.stchart-pane .chart { height: 260px; padding-inline: 0; padding-top: var(--s-4); }
.stchart-pane .xaxis { padding-inline: 0; border-bottom: 0; }

/* The most recent week is the one anybody came to see, so it is the one lit.
   The rest are the context it is read against. */
.col.is-now i { background: var(--acc); box-shadow: 0 0 22px -6px var(--acc); }
.col.is-now u { opacity: 1; transform: none; color: var(--acc-txt); }
/* The peak keeps a mark of its own, so the tallest bar means something even
   when the pointer is nowhere near it. */
.col.is-peak i { background: var(--acc2); }

/* ── the leaders ──────────────────────────────────────────────────────────── */
.podium {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: var(--s-4); margin-top: var(--s-4);
}
.pod {
  position: relative; overflow: hidden;
  border: 1px solid var(--ln); border-radius: var(--rad-large);
  background: linear-gradient(180deg, var(--sur), var(--bg) 82%);
  padding: var(--s-4);
  display: grid; gap: var(--s-3); align-content: start;
  transition: border-color var(--t-tint) ease, box-shadow var(--t-move) var(--ease),
              transform var(--t-move) var(--ease);
}
.pod::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  border-radius: inherit;
  background: radial-gradient(120% 70% at 50% -10%, var(--spot), transparent 70%);
  opacity: 0; transition: opacity var(--t-move) ease;
}
.pod:hover { border-color: var(--acc); box-shadow: 0 18px 40px -26px var(--scrim-base); transform: translateY(-2px); }
.pod:hover::before { opacity: 1; }
.pod > * { position: relative; z-index: 2; }

.pod-top { display: flex; align-items: center; gap: var(--s-3); min-width: 0; }
.pod-art {
  width: 46px; height: 46px; flex: none; border-radius: var(--rad-soft);
  object-fit: cover; border: 1px solid var(--ln);
  filter: saturate(.75) brightness(.85);
  transition: filter var(--t-move) ease, transform var(--t-move) var(--ease);
}
.pod:hover .pod-art { filter: none; transform: scale(1.05); }
.pod-art.none { display: grid; place-items: center; color: var(--rank); font-weight: 600; font-size: 18px; }
.pod-name { min-width: 0; }
.pod-name b {
  display: block; font-size: var(--t-sm); font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pod-rank {
  position: absolute; top: var(--s-3); right: var(--s-4);
  font-family: var(--mono); font-size: var(--t-xs); color: var(--rank);
  letter-spacing: var(--track-label);
}
.pod:nth-child(1) .pod-rank { color: var(--acc-txt); }

.pod-fig { display: flex; align-items: baseline; gap: var(--s-2); }
.pod-fig b {
  font-size: clamp(21px, 3vw, 27px); font-weight: 600; letter-spacing: -0.025em;
  font-variant-numeric: tabular-nums; color: var(--acc2);
}
.pod-fig span { color: var(--mut); font-size: var(--t-xs); }

/* Thirteen weeks as an area, drawn with a clip-path from a list of points the
   script builds. No library and no canvas: it is one element and one polygon,
   which is the right amount of machinery for a shape this small. */
.pod-spark {
  height: 42px; position: relative; overflow: hidden;
  border-radius: var(--rad-sharp);
  background: linear-gradient(180deg, var(--acc), transparent 92%);
  opacity: .55;
  clip-path: polygon(var(--pts, 0% 100%, 100% 100%));
  transition: opacity var(--t-move) ease;
  /* It grows from the baseline on arrival, the same way the bars do. */
  transform: scaleY(0); transform-origin: bottom;
}
[data-seen="1"] .pod-spark { transform: scaleY(1); transition: transform var(--t-grow) var(--ease), opacity var(--t-move) ease; }
.pod:hover .pod-spark { opacity: 1; }

/* The share of everything, as a bar under the figure. */
.pod-share { display: grid; gap: 5px; }
.pod-share small { color: var(--mut); font-size: var(--t-xs); font-family: var(--mono); }
.pod-share .bar { height: 3px; }

@media (prefers-reduced-motion: reduce) {
  .pod:hover { transform: none; }
  .pod:hover .pod-art { transform: none; }
  .pod-spark { transform: none; }
}

/* ── the long tail ────────────────────────────────────────────────────────── */
/* Rows arrive in sequence rather than all at once, which is what makes a list
   of sixty seven read as a ranking being counted out rather than as a wall
   appearing. The delay is capped: past about twenty rows the eye has taken the
   point, and a row that waits three seconds to appear looks broken. */
.ranking .row { animation: gh-rank-in var(--t-move) var(--ease) both; }
@keyframes gh-rank-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}
