/* ============================================================================
   Global leaderboard — shared by /leaderboard and the in-game modal.
   ============================================================================
   The same markup renders in two very different stylesheets: site.css (bone and
   red, light/dark) on the public pages, style.css (cold moonlight and sodium)
   inside the game. Rather than ship two skins, every colour goes through a
   --lb-* token.

   Dark is the baseline, written out in full rather than inherited: the game is
   always dark, and the host sheets' body/faint greys are tuned for prose at
   14px, not for a dense table of tabular numbers — they read as switched-off.
   The light theme then hands the tokens back to site.css, which is the only
   place a light palette exists.
   ========================================================================== */

.lb-root,
.lb-modal {
  --lb-line:        rgba(198, 206, 220, .16);
  --lb-line-strong: rgba(208, 216, 230, .34);
  --lb-panel:       rgba(16, 19, 25, .92);
  --lb-solid:       #0f1218;
  --lb-soft:        #161a22;
  --lb-hover:       #1c222c;
  --lb-text:        #f1ece0;
  --lb-text-2:      #e2dccd;
  --lb-body:        #cfc8b8;
  --lb-faint:       #9aa2b0;
  --lb-accent:      var(--red-bright, var(--sodium, #d9534f));
  --lb-shadow:      rgba(0, 0, 0, .72);
  --lb-display:     var(--display, var(--f-display, 'Staatliches', 'Arial Narrow', sans-serif));
  --lb-serif:       var(--serif, var(--f-mono, 'Special Elite', 'Courier New', monospace));
  --lb-sans:        var(--sans, var(--f-ui, 'Arial Narrow', Arial, sans-serif));
}

/* Light theme exists only on the public site, so it defers wholesale to the
   tokens site.css already balanced for it. */
:root[data-theme='light'] .lb-root,
:root[data-theme='light'] .lb-modal {
  --lb-line:        var(--line);
  --lb-line-strong: var(--line-strong);
  --lb-panel:       var(--panel);
  --lb-solid:       var(--panel-solid);
  --lb-soft:        var(--surface-soft);
  --lb-hover:       var(--hover-bg);
  --lb-text:        var(--text);
  --lb-text-2:      var(--text-secondary);
  --lb-body:        var(--text-body);
  --lb-faint:       var(--text-faint);
  --lb-shadow:      var(--shadow);
}

.lb-root {
  display: block;
  font-family: var(--lb-sans);
  color: var(--lb-text);
}

/* ---------------------------------------------------------------------------
   Page masthead. Short by design: the first ranks have to be on screen when
   the page loads, so this is a header, not a hero.
   ------------------------------------------------------------------------- */

.lb-hero { padding: clamp(26px, 4vw, 52px) 0 clamp(44px, 6vw, 80px); }
.lb-masthead {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(260px, 520px);
  gap: 18px clamp(24px, 5vw, 72px); align-items: end;
  padding-bottom: clamp(16px, 2.2vw, 26px);
}
.lb-masthead h1 {
  margin: 0;
  font: 400 clamp(38px, 6.2vw, 88px)/.86 var(--display, 'Staatliches', sans-serif);
  letter-spacing: clamp(3px, .8vw, 11px); text-wrap: balance;
  text-shadow: 0 0 45px rgba(179, 36, 42, .28);
}
.lb-masthead-copy {
  margin: 0; color: var(--text-body, #cfc8b8);
  font: 13px/1.75 var(--serif, 'Special Elite', monospace);
}

.lb-footnote {
  max-width: 82ch; margin: clamp(20px, 3vw, 32px) 0 0;
  color: var(--text-faint, #9aa2b0); font: 11px/1.9 var(--serif, 'Special Elite', monospace);
}

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

.lb-controls {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 10px 20px; margin-bottom: 10px;
}
.lb-tabs { display: flex; flex-wrap: wrap; gap: 7px; }

/* Scoped rather than inherited: site.css has a .filter-button and style.css
   does not, so the board owns the whole look in both places. */
.lb-root .filter-button {
  padding: 8px 16px; min-height: 34px;
  border: 1px solid var(--lb-line); background: transparent;
  color: var(--lb-faint); cursor: pointer;
  font: 11px/1 var(--lb-serif); letter-spacing: 2.2px; text-transform: uppercase;
  transition: color .16s ease, border-color .16s ease, background-color .16s ease;
}
.lb-root .filter-button:hover:not(:disabled) { color: var(--lb-text); border-color: var(--lb-line-strong); }
.lb-root .filter-button.active {
  color: var(--lb-text); border-color: var(--lb-accent);
  background: color-mix(in srgb, var(--lb-accent) 18%, transparent);
}
.lb-root .filter-button:disabled { opacity: .34; cursor: default; }

.lb-count { margin: 0; color: var(--lb-faint); font: 10px/1.6 var(--lb-serif); letter-spacing: 2px; text-transform: uppercase; }
.lb-note { margin: 0 0 14px; color: var(--lb-faint); font: 11px/1.6 var(--lb-serif); letter-spacing: .6px; }

/* ---------------------------------------------------------------------------
   Board
   ------------------------------------------------------------------------- */

.lb-board { border: 1px solid var(--lb-line); background: var(--lb-panel); }

/* One template, declared once and inherited by the header and every row, so a
   column can never drift between them. */
.lb-row {
  display: grid;
  grid-template-columns:
    minmax(44px, 56px)     /* rank    */
    minmax(0, 1fr)         /* run     */
    minmax(56px, 72px)     /* round   */
    minmax(60px, 88px)     /* kills   */
    minmax(56px, 76px)     /* downs   */
    minmax(62px, 86px)     /* revives */
    minmax(76px, 116px)    /* score   */
    minmax(58px, 82px)     /* time    */
    22px;                  /* chevron */
  align-items: center; gap: 10px;
  padding: 0 clamp(12px, 1.6vw, 20px);
  min-height: 62px;
  border-bottom: 1px solid var(--lb-line);
}
.lb-rows > .lb-row:last-child { border-bottom: 0; }

/* Every header cell is the same small caps label — including Round, which in a
   data row is the biggest number on the board. Without resetting it here the
   column heading renders in 23px display type and collides with its neighbour. */
.lb-row-head {
  min-height: 38px;
  background: var(--lb-soft);
  position: sticky; top: 68px; z-index: 4;
}
.lb-row-head > span {
  color: var(--lb-faint);
  font: 9px/1.2 var(--lb-serif) !important;
  letter-spacing: 1.8px; text-transform: uppercase;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lb-row-head .lb-c-num { text-align: right; }
/* Inside the game modal the board scrolls in its own card, not under a sticky
   site nav, so the header pins to the card instead. */
.lb-compact .lb-row-head { top: 0; }

button.lb-row {
  width: 100%; margin: 0; text-align: left; background: none;
  border-left: 0; border-right: 0; border-top: 0;
  cursor: pointer; color: inherit; font: inherit;
  transition: background-color .16s ease;
}
button.lb-row:hover, button.lb-row:focus-visible { background: var(--lb-hover); }
button.lb-row:focus-visible { outline: 2px solid var(--lb-accent); outline-offset: -2px; }
button.lb-row:hover .lb-c-chevron { color: var(--lb-accent); transform: translateX(2px); }

.lb-c-rank {
  font: 400 19px/1 var(--lb-display); letter-spacing: 2px; color: var(--lb-faint);
  font-variant-numeric: tabular-nums;
}
/* The top three read as placings, not as row numbers. */
.lb-rank-1 { --lb-medal: #e6c976; }
.lb-rank-2 { --lb-medal: #ccd0d8; }
.lb-rank-3 { --lb-medal: #cb8f58; }
.lb-rank-1, .lb-rank-2, .lb-rank-3 { box-shadow: inset 3px 0 0 var(--lb-medal); }
.lb-rank-1 .lb-c-rank, .lb-rank-2 .lb-c-rank, .lb-rank-3 .lb-c-rank { color: var(--lb-medal); }

.lb-c-name { display: flex; align-items: center; gap: 12px; min-width: 0; }
.lb-identity { display: grid; gap: 4px; min-width: 0; }
.lb-name-line { display: flex; align-items: center; gap: 8px; min-width: 0; }
.lb-name {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--lb-text); font: 400 18px/1.1 var(--lb-display); letter-spacing: 2.4px;
}
.lb-subline {
  color: var(--lb-faint); font: 9px/1.25 var(--lb-serif); letter-spacing: 1.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lb-flag { flex: 0 0 auto; font-size: 14px; line-height: 1; }
.lb-flag-empty { display: inline-block; width: 16px; color: var(--lb-faint); text-align: center; }
.lb-tag {
  flex: 0 0 auto; padding: 2px 6px; border: 1px solid var(--lb-line);
  color: var(--lb-faint); font: 8px/1.4 var(--lb-serif); letter-spacing: 1.4px; text-transform: uppercase;
}

.lb-c-num {
  text-align: right; font: 13px/1 var(--lb-serif); color: var(--lb-body);
  font-variant-numeric: tabular-nums;
  /* "1h 17m" breaking across two lines is what a column that is one character
     too narrow looks like. It must clip or shrink, never wrap. */
  white-space: nowrap;
}
.lb-rows .lb-c-round { color: var(--lb-text); font: 400 23px/1 var(--lb-display); letter-spacing: 1.5px; }
.lb-rows .lb-c-time { color: var(--lb-faint); font-size: 12px; }
.lb-c-chevron { color: var(--lb-faint); text-align: right; transition: transform .16s ease, color .16s ease; }

/* ---------------------------------------------------------------------------
   Overlapping character busts
   ---------------------------------------------------------------------------
   The squad of a run, stacked the way a party reads in a social app. The host
   leads; teammates fan out behind. Each bust is decorative (aria-hidden) — the
   row's aria-label carries the same names, because a focusable child inside a
   <button> row would be invalid markup.
   ------------------------------------------------------------------------- */

.lb-stack { display: flex; align-items: center; flex: 0 0 auto; }
.lb-seat { position: relative; display: block; z-index: calc(10 - var(--seat, 0)); }
.lb-seat + .lb-seat { margin-left: -13px; }
.lb-seat:hover { z-index: 20; }

.lb-portrait {
  display: block; overflow: hidden; position: relative;
  width: 34px; height: 34px; border-radius: 50%;
  border: 1px solid var(--lb-line-strong);
  background: var(--lb-soft);
  box-shadow: 0 0 0 2px var(--lb-solid);
  transition: transform .16s ease, border-color .16s ease;
}
/* The source art is a 900px chest-up bust inside a dark vignette. Dropped whole
   into a 34px circle the head is barely ten pixels across and every marine
   reads as the same dark smudge — Nikolai and Takeo, whose hood and cap fill
   the top of the frame, read as empty circles outright.

   So the image is oversized and offset to put one specific point of the art at
   the centre of the circle. That point is (47%, 37%) — the bridge of the nose,
   measured across all four busts — at 1.7x, which is the widest crop that still
   clears the vignette and keeps every hat inside the frame.

       left = (0.5 - scale * fx) * 100     top = (0.5 - scale * fy) * 100

   Recompute both if either number moves; they are not independent. */
.lb-portrait img {
  position: absolute; display: block;
  width: 170%; height: 170%;
  left: -29.9%; top: -12.9%;
  object-fit: cover;
  image-rendering: auto;
}
.lb-seat-subject .lb-portrait { border-color: var(--lb-accent); }
.lb-seat:hover .lb-portrait { transform: translateY(-2px) scale(1.06); border-color: var(--lb-accent); }

.lb-portrait-unknown { display: grid; place-items: center; }
.lb-portrait-initial { color: var(--lb-faint); font: 13px/1 var(--lb-display); letter-spacing: 0; }

/* Compound selector on purpose: the phone breakpoints below shrink
   .lb-portrait, and a single class there would out-cascade a single class here
   purely by source order — collapsing the dossier bust to a row-sized dot. */
.lb-portrait.lb-portrait-lg { width: 74px; height: 74px; flex: 0 0 auto; }
.lb-portrait-lg .lb-portrait-initial { font-size: 26px; }

/* Tooltip. Pointer-only on purpose: touch and keyboard reach the same
   information by opening the record, which lists every soldier in full. */
.lb-tip {
  position: absolute; left: 50%; bottom: calc(100% + 9px); z-index: 30;
  display: grid; gap: 2px; width: max-content; max-width: 220px;
  padding: 8px 11px; transform: translate(-50%, 4px);
  border: 1px solid var(--lb-line-strong); background: var(--lb-solid);
  box-shadow: 0 12px 34px var(--lb-shadow);
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .14s ease, transform .14s ease, visibility .14s;
}
.lb-seat:hover .lb-tip { opacity: 1; visibility: visible; transform: translate(-50%, 0); }
.lb-tip b { font: 400 14px/1.1 var(--lb-display); letter-spacing: 2px; color: var(--lb-text); }
.lb-tip i { font: normal 10px/1.3 var(--lb-serif); letter-spacing: 1.2px; color: var(--lb-accent); }
.lb-tip u {
  justify-self: start; margin-top: 2px; padding: 1px 5px; border: 1px solid var(--lb-line);
  text-decoration: none; font: 8px/1.4 var(--lb-serif); letter-spacing: 1.4px; color: var(--lb-faint);
}
.lb-tip-flag { position: absolute; top: 7px; right: 9px; font-size: 12px; }
/* The tooltip escapes the row, so nothing between it and the viewport may clip. */
.lb-board, .lb-rows, .lb-row, .lb-c-name { overflow: visible; }
/* Except the first row, whose tooltip would open under the sticky header. */
.lb-rows > .lb-row:first-child .lb-tip { bottom: auto; top: calc(100% + 9px); }

/* ---------------------------------------------------------------------------
   Loading, status, paging
   ------------------------------------------------------------------------- */

.lb-skeleton {
  height: 62px; border-bottom: 1px solid var(--lb-line);
  background: linear-gradient(90deg, transparent, var(--lb-hover), transparent);
  background-size: 200% 100%; animation: lb-shimmer 1.4s linear infinite;
}
@keyframes lb-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }

.lb-status { margin: 16px 0 0; color: var(--lb-faint); font: 12px/1.7 var(--lb-serif); }
.lb-status:empty { display: none; }
.lb-status.lb-error { color: var(--lb-accent); }

/* Hidden outright on a single page — a disabled pager is a control that says
   "there is more", and there is not. */
.lb-pager { display: flex; align-items: center; justify-content: center; gap: 16px; margin-top: 22px; }
.lb-pager[hidden] { display: none; }
.lb-pager-label { color: var(--lb-faint); font: 10px/1 var(--lb-serif); letter-spacing: 2px; text-transform: uppercase; }

/* ---------------------------------------------------------------------------
   Run record
   ------------------------------------------------------------------------- */

.lb-modal {
  position: fixed; inset: 0; z-index: 400;
  display: grid; place-items: center; padding: clamp(10px, 3vw, 40px);
  font-family: var(--lb-sans);
  color: var(--lb-text);
}
.lb-modal[hidden] { display: none; }
.lb-modal-scrim { position: absolute; inset: 0; background: rgba(3, 4, 6, .84); backdrop-filter: blur(3px); }
:root[data-theme='light'] .lb-modal-scrim { background: rgba(30, 33, 38, .55); }

.lb-modal-card {
  position: relative; width: min(960px, 100%); max-height: min(88vh, 900px); overflow-y: auto;
  border: 1px solid var(--lb-line-strong); background: var(--lb-solid);
  box-shadow: 0 40px 120px var(--lb-shadow);
  animation: lb-modal-in .18s ease-out;
}
@keyframes lb-modal-in { from { opacity: 0; transform: translateY(10px) scale(.99); } to { opacity: 1; transform: none; } }

.lb-modal-close {
  position: absolute; top: 10px; right: 10px; z-index: 2;
  width: 34px; height: 34px; border: 1px solid var(--lb-line);
  background: var(--lb-soft); color: var(--lb-body);
  /* Explicit system stack, not the host's condensed display face: the multiply
     sign is missing from Staatliches and substitutes into something that reads
     as a caret rather than a close button. */
  font: 20px/1 system-ui, -apple-system, 'Segoe UI', Arial, sans-serif; cursor: pointer;
}
.lb-modal-close:hover { color: var(--lb-text); border-color: var(--lb-line-strong); }
.lb-modal-body { padding: clamp(20px, 3.2vw, 38px); }
.lb-modal-body .eyebrow {
  margin: 0 0 10px; color: var(--lb-accent);
  font: 11px/1 var(--lb-serif); letter-spacing: 4px; text-transform: uppercase;
}

.lb-dossier-head { display: flex; flex-wrap: wrap; align-items: center; gap: 18px; padding-bottom: 20px; border-bottom: 1px solid var(--lb-line); }
.lb-dossier-rank {
  flex: 0 0 auto; min-width: 84px; padding: 10px 14px;
  border: 1px solid var(--lb-line-strong); background: var(--lb-soft); text-align: center;
}
.lb-dossier-rank b { display: block; font: 400 34px/1 var(--lb-display); letter-spacing: 2px; }
.lb-dossier-rank span { display: block; margin-top: 4px; color: var(--lb-faint); font: 8px/1 var(--lb-serif); letter-spacing: 2px; }
.lb-dossier-id { flex: 1 1 240px; min-width: 0; }
.lb-dossier-name {
  display: flex; align-items: center; gap: 12px; margin: 0; word-break: break-word;
  font: 400 clamp(26px, 4vw, 44px)/1 var(--lb-display); letter-spacing: 4px;
}
.lb-dossier-note { margin: 10px 0 0; color: var(--lb-faint); font: 10px/1.7 var(--lb-serif); letter-spacing: 1px; }

/* Fixed four columns rather than auto-fit. There are exactly eight tiles, so a
   fixed count fills two complete rows; auto-fit picks six at this width and
   leaves a bare grey block where the last two should sit. */
.lb-stat-grid {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px;
  margin: 22px 0 0; background: var(--lb-line); border: 1px solid var(--lb-line);
}
.lb-stat { padding: 14px 16px; background: var(--lb-solid); }
.lb-stat dt { margin: 0 0 7px; color: var(--lb-faint); font: 8px/1 var(--lb-serif); letter-spacing: 2px; text-transform: uppercase; }
.lb-stat dd { margin: 0; font: 400 24px/1 var(--lb-display); letter-spacing: 1.6px; font-variant-numeric: tabular-nums; }
.lb-stat dd small { display: block; margin-top: 6px; color: var(--lb-faint); font: 10px/1.4 var(--lb-serif); letter-spacing: .5px; }
.lb-stat-empty dd { color: var(--lb-faint); }

.lb-runs-title { margin: 30px 0 12px; color: var(--lb-faint); font: 9px/1 var(--lb-serif); letter-spacing: 2.5px; text-transform: uppercase; }
.lb-squad-panel { border: 1px solid var(--lb-line); }

.lb-squad-row {
  display: grid; grid-template-columns: minmax(0, 1.6fr) repeat(4, minmax(50px, .7fr));
  gap: 10px; align-items: center;
  padding: 11px clamp(12px, 2vw, 18px); border-bottom: 1px solid var(--lb-line);
}
.lb-squad-row:last-child { border-bottom: 0; }
.lb-squad-head { background: var(--lb-soft); color: var(--lb-faint); font: 8px/1 var(--lb-serif); letter-spacing: 2px; text-transform: uppercase; }
.lb-squad-head span:not(:first-child) { text-align: right; }
.lb-squad-name { display: flex; align-items: center; gap: 10px; min-width: 0; }
.lb-squad-id { display: grid; gap: 3px; min-width: 0; }
.lb-squad-top { display: flex; align-items: center; gap: 8px; min-width: 0; font: 400 15px/1.1 var(--lb-display); letter-spacing: 2px; color: var(--lb-text); }
.lb-squad-top > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lb-squad-character { color: var(--lb-faint); font: 9px/1.2 var(--lb-serif); letter-spacing: 1.4px; }
.lb-squad-num { text-align: right; font: 12px/1 var(--lb-serif); color: var(--lb-body); font-variant-numeric: tabular-nums; }
.lb-squad-you .lb-squad-top { color: var(--lb-accent); }
.lb-squad-detail { grid-column: 1 / -1; margin-top: 6px; color: var(--lb-faint); font: 10px/1.7 var(--lb-serif); letter-spacing: .5px; }

/* ---------------------------------------------------------------------------
   In-game modal (compact)
   ---------------------------------------------------------------------------
   The game's own screen shell wraps the board. `.panel.leaderboard-panel`
   rather than `.leaderboard-panel` alone, because style.css sets the width on
   `.panel.wide` and a single class would lose the cascade to it.
   ------------------------------------------------------------------------- */

.panel.leaderboard-panel { width: min(1180px, 96vw); text-align: left; }
.leaderboard-panel .panel-kicker,
.leaderboard-panel > h2,
.leaderboard-panel > .panel-lead { text-align: center; }
.leaderboard-panel #leaderboard-mount { margin-top: 18px; }
.leaderboard-panel .row-buttons { margin-top: 18px; }

.lb-compact .lb-row { min-height: 56px; }
.lb-compact .lb-skeleton { height: 56px; }
.lb-compact .lb-name { font-size: 16px; }
.lb-compact .lb-portrait { width: 30px; height: 30px; }
.lb-compact .lb-seat + .lb-seat { margin-left: -11px; }

/* ---------------------------------------------------------------------------
   Responsive
   ---------------------------------------------------------------------------
   Columns drop by class, never by nth-child: the row is built in JS and a
   positional selector would silently retarget the moment a column moves.
   Everything hidden here is still in the run record, one tap away.
   ------------------------------------------------------------------------- */

@media (max-width: 1024px) {
  .lb-row-head { top: 0; }
  .lb-masthead { grid-template-columns: minmax(0, 1fr); }
}

/* Laptop → tablet: drop revives, then downs. Score and time stay because they
   are the two numbers people actually compare after the round. */
@media (max-width: 1000px) {
  .lb-row { gap: 8px; }
  .lb-c-revives { display: none; }
  .lb-squad-row { grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(46px, .7fr)); }
  .lb-squad-revives { display: none; }
}
@media (max-width: 860px) {
  .lb-row {
    grid-template-columns:
      minmax(32px, 42px) minmax(0, 1fr) minmax(48px, 60px) minmax(54px, 78px) minmax(52px, 72px) 16px;
  }
  .lb-c-downs, .lb-c-score { display: none; }
}

/* ---------------------------------------------------------------------------
   Phone. Below this the row stops being a table row.
   ---------------------------------------------------------------------------
   Five numeric columns cannot be made to fit 320px by shrinking them — the last
   one wraps to its own line and the row tears in half, which is exactly what a
   grid does when its minimums exceed the container. So the row becomes a
   two-line card instead: identity on the left across both lines, the round and
   the kill count stacked on the right. Only three tracks, the middle one
   `minmax(0, 1fr)`, so there is no width at which it can overflow.

   The column header is hidden here because the values label themselves — the
   pseudo-elements below put "RND" and "KILLS" on the numbers directly.
   ------------------------------------------------------------------------- */
@media (max-width: 620px) {
  .lb-row-head { display: none; }

  .lb-row {
    grid-template-columns: 22px minmax(0, 1fr) auto;
    grid-template-areas:
      'rank who round'
      'rank who kills';
    row-gap: 2px; column-gap: 9px;
    padding: 11px 12px; min-height: 0;
  }
  .lb-c-rank   { grid-area: rank;  align-self: center; }
  .lb-c-name   { grid-area: who;   align-self: center; }
  .lb-rows .lb-c-round { grid-area: round; align-self: end; }
  .lb-c-kills  { grid-area: kills; align-self: start; }
  .lb-c-downs, .lb-c-revives, .lb-c-score, .lb-c-time, .lb-c-chevron { display: none; }

  .lb-c-rank { font-size: 15px; letter-spacing: .5px; }
  .lb-rows .lb-c-round { font-size: 22px; letter-spacing: .5px; }
  /* Labels move onto the numbers now that the header is gone. */
  .lb-rows .lb-c-round::before,
  .lb-rows .lb-c-kills::after {
    color: var(--lb-faint);
    font: 8px/1 var(--lb-serif); letter-spacing: 1.2px; text-transform: uppercase;
  }
  .lb-rows .lb-c-round::before { content: 'RND '; }
  .lb-rows .lb-c-kills::after { content: ' KILLS'; }
  .lb-c-num { font-size: 11px; }

  .lb-name { font-size: 14px; letter-spacing: 1.3px; }
  .lb-subline { font-size: 8px; letter-spacing: 1px; }
  .lb-c-name { gap: 9px; }
  .lb-identity { gap: 3px; }
  .lb-tag { display: none; }
  .lb-portrait { width: 26px; height: 26px; box-shadow: 0 0 0 1.5px var(--lb-solid); }
  .lb-seat + .lb-seat { margin-left: -10px; }
  /* No hover on a touch screen, so the tooltip is dead weight that can only
     get in the way of a tap. The record has every name in full. */
  .lb-tip { display: none; }

  .lb-controls { gap: 8px 12px; }
  .lb-root .filter-button { padding: 7px 12px; min-height: 32px; font-size: 10px; letter-spacing: 1.6px; }
  .lb-count { font-size: 9px; letter-spacing: 1.2px; }
  .lb-note { font-size: 10px; margin-bottom: 12px; }
  .lb-skeleton { height: 64px; }

  /* The masthead is a header, not a hero, and on a phone every line of it is a
     line of standings pushed off the screen. The intro paragraph is clamped
     rather than removed — it is the only place the "cheat-free runs only" rule
     is stated, and the full text is still there for anyone who wants it. */
  .lb-hero { padding-top: 18px; }
  .lb-masthead { gap: 12px; padding-bottom: 14px; }
  .lb-masthead h1 { font-size: clamp(30px, 11vw, 44px); letter-spacing: 2.5px; }
  .lb-masthead-copy {
    font-size: 11px; line-height: 1.65;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden;
  }
  .lb-hero .eyebrow { font-size: 9px; letter-spacing: 2.5px; }
  .lb-footnote { font-size: 10px; line-height: 1.8; }

  .lb-modal { padding: 0; }
  .lb-modal-card { width: 100%; max-height: 100vh; height: 100%; border: 0; }
  .lb-modal-body { padding: 20px 14px 32px; }
  .lb-stat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .lb-stat { padding: 12px 13px; }
  .lb-stat dd { font-size: 20px; }
  .lb-dossier-head { gap: 12px; padding-right: 40px; }
  .lb-portrait.lb-portrait-lg { width: 54px; height: 54px; }
  .lb-dossier-rank { min-width: 62px; padding: 8px 10px; }
  .lb-dossier-rank b { font-size: 24px; }
  .lb-dossier-name { font-size: 26px; letter-spacing: 2.5px; }

  /* The per-player stat columns stop fitting; the detail line under each
     soldier already carries the same numbers in words. */
  .lb-squad-row { grid-template-columns: minmax(0, 1fr) repeat(2, minmax(42px, .55fr)); gap: 8px; }
  .lb-squad-revives, .lb-squad-score { display: none; }
  .lb-squad-detail { font-size: 9px; line-height: 1.65; }
  .lb-squad-top { font-size: 14px; letter-spacing: 1.4px; }
}

/* 320px. The smallest screen anyone still ships, and the width at which a
   three-marine stack plus a name plus a number stops being negotiable. */
@media (max-width: 380px) {
  .lb-row { column-gap: 7px; padding: 10px 9px; }
  .lb-portrait { width: 23px; height: 23px; }
  .lb-portrait.lb-portrait-lg { width: 48px; height: 48px; }
  .lb-seat + .lb-seat { margin-left: -9px; }
  .lb-name { font-size: 13px; letter-spacing: 1px; }
  .lb-subline { font-size: 7.5px; letter-spacing: .8px; }
  .lb-rows .lb-c-round { font-size: 20px; }
  .lb-c-num { font-size: 10px; }
  .lb-flag { font-size: 12px; }
  .lb-root .filter-button { padding: 6px 10px; font-size: 9px; letter-spacing: 1.2px; }
  .lb-masthead h1 { letter-spacing: 2px; }
  .lb-stat-grid { grid-template-columns: minmax(0, 1fr); }
  .lb-squad-row { grid-template-columns: minmax(0, 1fr) minmax(40px, .5fr); }
  .lb-squad-downs { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .lb-modal-card, .lb-skeleton { animation: none; }
  button.lb-row, .lb-c-chevron, .lb-portrait, .lb-tip { transition: none; }
}
