/* The three public pages: a player (/u/NAME), a match (/m/TOKEN) and the world
   table (/world).

   The page SHELL — .page, .page-head, .page-plain, .page-foot and the rest —
   is not in here. It lives in creators.css, which despite the name is the
   house long-form page layout and was simply written first for that page.
   These three load both files and add only what is theirs, because forking a
   second copy of the shell is how two pages start drifting apart.

   Everything below is built for a page that is read rather than played:
   scoreboards, rank chips and a list of matches. */

/* ---------------------------------------------------------------- the head
   Name, flag and level, on one line that wraps to two on a phone. The name is
   the biggest thing on the page because it is what the page is about, and it
   is fluid for the same reason .page-hero h1 is — the display face is
   fixed-width per character, so a sixteen-character name at a fixed size has
   nowhere to go on a narrow screen. */
.pf-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 18px;
  flex-wrap: wrap;
  padding: 4px 0 22px;
}
.pf-id { display: flex; align-items: center; gap: 12px; min-width: 0; }
.pf-name {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  letter-spacing: var(--display-spacing);
  font-size: clamp(1.3rem, 6vw, 2.4rem);
  line-height: 1.1;
  margin: 0;
  overflow-wrap: anywhere;
}
/* The flag and its two letters, always together. On Windows, which ships no
   flag glyphs, the emoji renders as the same two letters — so the pair reads
   as "DE DE" there rather than as a mystery box, which is the better of the
   two failures. */
.pf-flag { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.pf-flag-glyph { font-size: 28px; line-height: 1; }
.pf-flag-code {
  color: var(--muted);
  font-size: 12px;
  letter-spacing: 0.1em;
}

/* The name and, under it, the badge the level has earned. Two lines in a
   column so the flag stays beside the NAME rather than floating next to a
   two-line block — .pf-id centres its children, and a title line under the
   name would otherwise drag the flag down to the middle of both. */
.pf-idcol { min-width: 0; display: flex; flex-direction: column; gap: 6px; }
/* The title. It is the one thing on this page that is neither a number nor a
   rank, and it is what somebody would actually call themselves — so it sits
   directly under the name, in the tier's ink, at the size of a subtitle. */
.pf-title { display: inline-flex; align-items: center; gap: 7px; }
.pf-title .badge-icon { width: 18px; height: 18px; flex: none; }
.pf-title-name {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  letter-spacing: var(--body-spacing);
  font-size: 13px;
  color: currentColor;
}
.pf-title-lv { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------- the share row
   Right of the name on a wide screen, under it on a phone — .pf-head already
   wraps, so this is one flex child that goes where there is room.

   ONE of the two buttons is shown, never both, and the pointer decides which:
   a coarse pointer gets Share, which opens the system sheet where every
   installed app already lives (this is how Instagram and TikTok are reached —
   see the note in profile-page.js), and a fine pointer gets Copy link, because
   a desktop share sheet is either absent or an OS panel nobody wants. The same
   media test drives shareVia(), so the label never promises the wrong thing.

   The network links go with the desktop half for the same reason: on a phone
   they are all in the sheet already, and eight chips under a Share button
   would be eight ways to do what the button just did. */
.pf-share { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; max-width: 380px; }
.pf-share button { padding: 9px 18px; font-size: 13px; }
.pf-share-go { display: none; }
@media (pointer: coarse) {
  .pf-share-go { display: block; }
  .pf-share-copy, .pf-share-nets { display: none; }
}
.pf-share-nets { display: flex; flex-wrap: wrap; gap: 5px; justify-content: flex-end; }
/* Small, quiet and all the same weight: none of the eight is the recommended
   one, and a row where one is louder reads as an ad for that network. */
.pf-share-to {
  font-size: 11px;
  line-height: 1;
  padding: 6px 9px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: var(--muted);
  text-decoration: none;
  white-space: nowrap;
}
.pf-share-to:hover { color: var(--text); border-color: var(--accent); background: var(--panel-3); }
@media (max-width: 640px) {
  /* Under the name rather than jammed against the right edge of it. */
  .pf-share { max-width: none; width: 100%; align-items: flex-start; }
  .pf-share-nets { justify-content: flex-start; }
}

/* --------------------------------------------------------------- the cards
   One card per mode, each with its headline number, its supporting line and
   its rank chips. The grid is two columns where there is room and one where
   there is not; nothing here reflows into three, because a rank chip beside a
   six-digit score needs a certain width to stay on one line. */
.pf-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 14px;
  margin-bottom: 20px;
}
.pf-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 18px 20px;
}
.pf-card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
}
.pf-card-head h2 {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  letter-spacing: var(--display-spacing);
  font-size: 0.85rem;
  margin: 0;
  /* The rule under a heading belongs to the head, which spans the card. Said
     explicitly because this head is also used inside .page-plain (the badge
     case), and creators.css gives every h2 in there a border of its own —
     which lands as a second, short line under the word. */
  border-bottom: none;
  padding-bottom: 0;
}
.pf-card-note { color: var(--muted); font-size: 11px; }

/* The one number a card is opened for. */
.pf-big {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  letter-spacing: var(--display-spacing);
  font-size: clamp(1.6rem, 7vw, 2.4rem);
  font-variant-numeric: tabular-nums;
  line-height: 1.05;
}
.pf-big-unit { font-size: 0.5em; color: var(--muted); margin-left: 6px; }
.pf-sub { color: var(--muted); font-size: 13px; line-height: 1.6; margin: 6px 0 0; }

/* ----------------------------------------------------------- the rank chips
   GLOBAL #12 / DE #3. Two small blocks, side by side, each a label over a
   number — the shape is doing the work here, so they stay legible next to a
   headline figure four times their size.

   The country chip is the accented one. On a page that already says the
   global rank in the same row, the interesting half is nearly always "and
   where does that put me at home". */
.pf-ranks { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 12px; }
.pf-rank {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  padding: 6px 14px;
  border-radius: 10px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  min-width: 84px;
}
.pf-rank-k {
  color: var(--muted);
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}
.pf-rank-v {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  font-variant-numeric: tabular-nums;
  font-size: 17px;
  line-height: 1.1;
}
.pf-rank.country { border-color: var(--accent); }
.pf-rank.country .pf-rank-v { color: var(--accent); }
/* The denominator, which is what stops "#3" being unreadable. Third of four
   and third of nine hundred are not the same achievement. */
.pf-rank-of { color: var(--muted); font-size: 9.5px; font-variant-numeric: tabular-nums; }

/* ----------------------------------------------------------- the form strip
   The last dozen ranked results as one row of squares, oldest on the left.
   The shape of a run is the whole point — five greens then four reds is a
   story the same twelve rows further down the page do not tell — so the pips
   are colour and position and carry no text at all.

   Each is a link to its match, which is why they are sized like something you
   can hit: 14px with a 4px gap clears the 24px minimum once the row's own
   padding is counted, and on a phone the row is the easiest target on the
   card. */
.pf-form { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 14px; }
.pf-pips { display: flex; gap: 4px; padding: 4px 0; }
.pf-pip {
  display: block;
  width: 14px;
  height: 14px;
  border-radius: 4px;
  border: 1px solid var(--border);
  text-decoration: none;
}
.pf-pip.win { background: var(--ok); border-color: var(--ok); }
.pf-pip.loss { background: var(--danger); border-color: var(--danger); }
.pf-pip:hover { outline: 2px solid var(--accent); outline-offset: 1px; }
.pf-form-k { color: var(--muted); font-size: 11px; }
/* Only ever drawn at two in a row or more, so it is always news. */
.pf-streak {
  font-size: 11px;
  border-radius: 999px;
  padding: 2px 9px;
  border: 1px solid var(--border);
  color: var(--muted);
}
.pf-streak.win { color: var(--ok); border-color: var(--ok); }
.pf-streak.loss { color: var(--danger); border-color: var(--danger); }

/* -------------------------------------------------------------- the aside
   Avatar, joined date and level, in the narrow column beside the cards on a
   wide screen and above them on a narrow one. */
.pf-body { display: grid; grid-template-columns: 200px 1fr; gap: 14px; align-items: start; }
@media (max-width: 760px) { .pf-body { grid-template-columns: 1fr; } }

.pf-aside { display: flex; flex-direction: column; gap: 14px; }
.pf-avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 18px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 16px;
}
.pf-avatar .sz-av { border-radius: 12px; }

.pf-facts {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 14px 16px;
}
.pf-fact {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 6px 0;
  border-bottom: 1px solid var(--border);
}
.pf-fact:last-child { border-bottom: none; }
.pf-fact-k { color: var(--muted); font-size: 12px; }
.pf-fact-v { font-weight: 700; font-variant-numeric: tabular-nums; font-size: 13px; }

/* The level bar. Deliberately the same idea as the one on the menu, without
   being the same code: level.js draws the signed-in player's own and knows how
   to animate a level-up, and this only ever draws a number that is already
   final. */
.pf-level-row { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.pf-level-n {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  letter-spacing: var(--display-spacing);
  font-size: 20px;
  color: var(--accent);
}
.pf-level-k { color: var(--muted); font-size: 10px; text-transform: uppercase; letter-spacing: 0.1em; }
.pf-bar {
  height: 6px;
  border-radius: 999px;
  background: var(--well);
  border: 1px solid var(--border);
  overflow: hidden;
  margin: 8px 0 4px;
}
.pf-bar span { display: block; height: 100%; background: var(--accent); }
.pf-xp { color: var(--muted); font-size: 11px; font-variant-numeric: tabular-nums; }
/* The breakdown, in the supporter heart's own ink so the line and the badge
   further down the page are visibly the same fact. */
.pf-level-bonus { color: var(--badge-5); margin-top: 3px; }

/* -------------------------------------------------------------- records
   The personal-best grid. Reuses .stat / .stat-row from creators.css, which is
   exactly this shape already. */

/* --------------------------------------------------------- the badge case
   All twenty rungs, earned and not, in a grid that fills the page width. The
   tile itself — sprite, name, rung, lit or grey — is in style.css, because a
   badge should look the same wherever it is drawn; this only decides how many
   fit in a row. minmax(96px) puts seven across a desktop page and three on the
   narrowest phone, which is the smallest a tile can be and still hold
   "Cabinet Regular" on two lines. */
.pf-badges {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 8px;
}
/* What the next rung is and how far off, under the case. The one line on this
   page addressed to the person climbing rather than the person visiting. */
.pf-badge-next {
  color: var(--muted);
  font-size: 12px;
  margin: 12px 0 0;
  font-variant-numeric: tabular-nums;
}
.pf-badge-next b { color: var(--text); font-weight: 700; }

/* ------------------------------------------------------ the last-20 tiles
   Reuses .stat / .stat-row from creators.css. Two of these tiles hold a name
   rather than a number — the map and the opponent — and the display face at
   22px puts "Twin Towers" through the side of a 130px tile, so those are
   marked and set smaller. They are still the tile's headline, just a headline
   made of letters. */
.stat.pf-stat-text .n {
  font-size: 15px;
  line-height: 1.35;
  overflow-wrap: anywhere;
}
.stat.pf-stat-text a { color: inherit; text-decoration: none; }
.stat.pf-stat-text a:hover { color: var(--accent); }
/* The caveat under the row: which matches these six were counted over. */
.pf-stat-note { color: var(--muted); font-size: 12px; margin: 0 0 14px; }

/* ------------------------------------------------------- recent matches
   A list of rows, each a link. Grid rather than flex, so the outcome, the
   score, the opponent and the time line up down the column — this is scanned,
   not read, and a ragged left edge on the scores defeats the whole point. */
.pf-matches { display: flex; flex-direction: column; gap: 6px; }
.pf-match {
  display: grid;
  grid-template-columns: 54px 62px 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-radius: 10px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  color: inherit;
  text-decoration: none;
}
.pf-match:hover { border-color: var(--accent); background: var(--panel-3); }
.pf-match-out {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  font-size: 11px;
  letter-spacing: 0.08em;
}
.pf-match.win .pf-match-out { color: var(--ok); }
.pf-match.loss .pf-match-out { color: var(--danger); }
.pf-match-score { font-variant-numeric: tabular-nums; font-weight: 700; font-size: 14px; }
.pf-match-who { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; }
.pf-match-who .pf-vs { color: var(--muted); font-size: 12px; margin-right: 5px; }
/* Which map the round started on, after the opponent's name. Quiet and first
   to be dropped on a narrow screen: it is the least of the four things a row
   says, and the match page behind the link says it properly. */
.pf-match-map { color: var(--muted); font-size: 12px; margin-left: 7px; }
.pf-match-when { color: var(--muted); font-size: 12px; white-space: nowrap; }
/* Practice against the computer is kept and marked, rather than hidden: it is
   most of what a new player has to show, and a page with nothing on it for the
   first week is worse than one that says who they were playing. */
.pf-cpu {
  font-size: 9.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 1px 5px;
  margin-left: 6px;
}
@media (max-width: 560px) {
  /* The duration is the first thing to go: it is the least of the four and the
     match page has it. */
  .pf-match { grid-template-columns: 48px 56px 1fr; }
  .pf-match-when { grid-column: 1 / -1; }
  .pf-match-map { display: none; }
}

/* ---------------------------------------------------------- the match page
   Two players either side of a score. The same head/aside vocabulary as the
   profile, so the two pages read as one place. */
.mt-score {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 14px;
  padding: 18px 0 6px;
}
.mt-side { display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center; min-width: 0; }
.mt-side a, .mt-side span.mt-who {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  letter-spacing: var(--display-spacing);
  font-size: clamp(0.95rem, 3.6vw, 1.4rem);
  color: inherit;
  text-decoration: none;
  overflow-wrap: anywhere;
}
.mt-side a:hover { color: var(--accent); }
/* Stands in for the avatar the computer does not have, so both sides of the
   score share one baseline. */
.mt-noav { width: 72px; height: 72px; }
.mt-side.win a, .mt-side.win span.mt-who { color: var(--ok); }
.mt-ko {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  font-variant-numeric: tabular-nums;
  font-size: clamp(2rem, 11vw, 3.4rem);
  line-height: 1;
  white-space: nowrap;
}
.mt-ko-dash { color: var(--muted); margin: 0 6px; }
.mt-meta { text-align: center; color: var(--muted); font-size: 13px; margin: 4px 0 22px; }
.mt-meta b { color: var(--text); font-weight: 700; }

/* The two stat columns. A three-column grid — label in the middle, a value
   either side — so the two players are compared across a row rather than read
   as two separate lists. */
/* Width-limited and centred rather than filling the card: the two values are
   read against each other across the label, and stretched to a 900px card they
   end up a hand's width apart with the thing they are being compared on
   stranded in the middle. */
.mt-stats {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 0 18px;
  max-width: 520px;
  margin: 0 auto;
}
.mt-stat-k {
  color: var(--muted);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  text-align: center;
  padding: 9px 0;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.mt-stat-v {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  padding: 9px 0;
  border-bottom: 1px solid var(--border);
}
.mt-stat-v.left { text-align: right; }
.mt-stat-v.right { text-align: left; }
/* Whoever is ahead on a row. Colour only, never bold-on-top-of-bold: every
   value on this grid is already 700, and a second emphasis on one of them
   makes the rest look disabled. */
.mt-stat-v.better { color: var(--accent); }
.mt-stats > :nth-last-child(-n + 3) { border-bottom: none; }

/* --------------------------------------------------------- the world table */
.wt-row {
  display: grid;
  grid-template-columns: 44px 34px 1fr auto auto;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-radius: 10px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  color: inherit;
  text-decoration: none;
  margin-bottom: 6px;
}
.wt-row:hover { border-color: var(--accent); background: var(--panel-3); }
.wt-rank { color: var(--muted); font-variant-numeric: tabular-nums; font-size: 13px; }
.wt-flag { font-size: 22px; line-height: 1; }
.wt-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The caveat on the number at the end of the row, kept beside the name rather
   than given a column of its own — see the note in world-page.js. */
.wt-sub { color: var(--muted); font-size: 11px; margin-left: 8px; }
.wt-n { font-variant-numeric: tabular-nums; font-weight: 700; font-size: 14px; min-width: 62px; text-align: right; }
.wt-k { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; }

/* ------------------------------------------------------------ empty states
   Every one of these pages can legitimately have nothing to show — a player
   who has not finished a match, a match with no reports, a world with two
   countries in it. None of them is an error, and none of them should look like
   one. */
.pf-empty { color: var(--muted); font-size: 13px; line-height: 1.6; margin: 0; }
/* The way back out of a country's ladder. Uses .page-back from creators.css so
   it matches the one at the top of every page rather than being a second,
   differently coloured, back link. */
.pf-backline { margin: 14px 0 0; }
.pf-loading { color: var(--muted); font-size: 14px; padding: 40px 0; text-align: center; }
.pf-missing { text-align: center; padding: 50px 20px; }
.pf-missing h1 {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  letter-spacing: var(--display-spacing);
  font-size: clamp(1.1rem, 5vw, 1.7rem);
  margin: 0 0 10px;
}
.pf-missing p { color: var(--muted); font-size: 14px; line-height: 1.7; max-width: 46ch; margin: 0 auto; }
