/*
 * Holocron Rating Index — Design System
 * Dark theme, holocron crystal aesthetic.
 */

/* ============================================================
   DESIGN TOKENS
   ============================================================ */

:root {
  /* Colors — from Pencil design (design/hri-design.pen) */
  --bg:              #0B1120;
  --surface:         #111827;
  --card:            #1A2332;
  --card-hover:      #1E2A3D;
  --input:           #0F1A2A;
  --border:          #1E3A5F;
  --text-primary:    #F1F5F9;
  --text-secondary:  #CBD5E1;
  --text-tertiary:   #94A3B8;
  --accent:          #0EA5E9;
  --accent-hover:    #38BDF8;
  --accent-surface:  rgba(14, 165, 233, 0.08);
  --accent-glow:     rgba(56, 189, 248, 0.2);
  --positive:        #22C55E;
  --negative:        #EF4444;
  --warning:         #F59E0B;

  /* Tier colors — distinct hues for instant recognition */
  --tier-planetary:  #22C55E;
  --tier-sector:     #F59E0B;
  --tier-regional:   #0EA5E9;
  --tier-galactic:   #7C3AED;

  /* Rank medal colors */
  --rank-gold:       #F59E0B;
  --rank-silver:     #CBD5E1;
  --rank-bronze:     #D97706;

  /* Typography — Geist family from Pencil design */
  --font-display: 'Geist', system-ui, sans-serif;
  --font-body:    'Inter', system-ui, sans-serif;
  --font-data:    'Geist Mono', 'JetBrains Mono', monospace;

  /* Spacing (8px base) */
  --space-2xs:  4px;
  --space-xs:   8px;
  --space-sm:   12px;
  --space-md:   16px;
  --space-lg:   24px;
  --space-xl:   32px;
  --space-2xl:  48px;
  --space-3xl:  64px;

  /* Border radii */
  --radius-sm:   4px;
  --radius-md:   8px;
  --radius-lg:   12px;
  --radius-full: 20px;
}

/* ============================================================
   RESET / BASE
   ============================================================ */

*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 16px;
  -webkit-text-size-adjust: 100%;
}

body {
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.5;
  background-color: var(--bg);
  color: var(--text-primary);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

a {
  color: var(--accent);
  text-decoration: none;
}

a:hover {
  color: var(--accent-hover);
}

img, svg {
  display: block;
  max-width: 100%;
}

table {
  border-collapse: collapse;
}

/* ============================================================
   LAYOUT
   ============================================================ */

.container {
  width: 100%;
  max-width: 1440px;
  margin-inline: auto;
  padding-inline: 32px;
}

main {
  flex: 1;
}

.content-area {
  padding: 32px 80px 48px;
}

/* ============================================================
   SITE HEADER (matches Pencil NavBar component)
   ============================================================ */

.site-header {
  background-color: var(--surface);
  position: sticky;
  top: 0;
  z-index: 100;
}

.site-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 56px;
  padding: 0 32px;
}

.nav-left { display: flex; align-items: center; }

.site-logo {
  display: flex;
  align-items: center;
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--text-primary);
  transition: color 0.15s ease;
}

.site-logo:hover {
  color: var(--accent);
}

.nav-logo-img {
  height: 36px;
  width: auto;
  transition: opacity 0.15s ease;
}

.site-logo:hover .nav-logo-img { opacity: 0.85; }

.nav-links {
  display: flex;
  align-items: center;
  gap: var(--space-lg);
}

.nav-link {
  font-family: var(--font-body);
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--text-secondary);
  transition: color 0.15s ease;
}

.nav-link:hover {
  color: var(--text-primary);
}

.nav-link--active {
  color: var(--accent);
  font-weight: 600;
}

/* ============================================================
   SITE FOOTER
   ============================================================ */

.site-footer {
  background-color: var(--surface);
  border-top: 1px solid var(--border);
  padding-block: var(--space-lg);
  margin-top: auto;
}

.footer-text {
  font-size: 0.8125rem;
  color: var(--text-tertiary);
  text-align: center;
  line-height: 1.6;
}

.footer-link {
  color: var(--text-secondary);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.footer-link:hover {
  color: var(--text-primary);
}

/* ============================================================
   TYPOGRAPHY
   ============================================================ */

.heading-xl {
  font-family: var(--font-display);
  font-size: 1.75rem;
  font-weight: 700;
  color: var(--text-primary);
  line-height: 1.2;
  letter-spacing: -0.01em;
}

.heading-lg {
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--text-primary);
  line-height: 1.3;
}

.label {
  font-family: var(--font-body);
  font-size: 0.6875rem;
  font-weight: 600;
  color: var(--text-tertiary);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* ============================================================
   DATA TYPOGRAPHY
   ============================================================ */

.data {
  font-family: var(--font-data);
  font-size: 0.8125rem;
  font-weight: 400;
  color: var(--text-primary);
}

.data-lg {
  font-family: var(--font-data);
  font-size: 1rem;
  font-weight: 500;
  color: var(--text-primary);
}

/* ============================================================
   RATING NUMBERS
   Glow ONLY on hero and table rating — no glow elsewhere.
   ============================================================ */

.rating-number {
  font-family: var(--font-data);
  font-weight: 700;
  color: var(--accent);
  line-height: 1;
}

/* Hero: large glow (profile page, featured display) */
.rating-number--hero {
  font-size: 3rem;  /* 48px */
  text-shadow: 0 0 12px var(--accent-glow);
}

/* Table: subtle glow in the ratings column */
.rating-number--table {
  font-size: 0.8125rem;
  text-shadow: 0 0 8px var(--accent-glow);
}

/* ============================================================
   RATING CHANGE
   ============================================================ */

.rating-change {
  font-family: var(--font-data);
  font-size: 0.8125rem;
  font-weight: 500;
}

.rating-change--positive {
  color: var(--positive);
}

.rating-change--negative {
  color: var(--negative);
}

/* ============================================================
   RATING DEVIATION
   ============================================================ */

.rd {
  font-family: var(--font-data);
  font-size: 0.6875rem;
  color: var(--text-tertiary);
}

/* ============================================================
   HERO SECTION (Rankings page top)
   ============================================================ */

.hero-section {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  flex-wrap: wrap;
  gap: 28px 40px;
  padding: 48px 80px 40px;
  border-bottom: 1px solid var(--border);
}

.hero-lockup {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  min-width: 0;
}

.hero-logo {
  height: 160px;
  width: auto;
  flex-shrink: 0;
  display: block;
  filter: drop-shadow(0 0 24px rgba(14, 165, 233, 0.2));
}

.hero-title {
  font-family: var(--font-display);
  font-size: 44px;
  font-weight: 700;
  letter-spacing: -0.03em;
  color: var(--text-primary);
  margin: 0;
  line-height: 1;
}

.hero-sub {
  font-family: var(--font-body);
  font-size: 16px;
  font-weight: 400;
  color: var(--text-secondary);
  margin: 0;
  letter-spacing: 0.005em;
  line-height: 1.4;
}

.hero-sub strong {
  color: var(--accent);
  font-weight: 600;
}

/* Global stats banner at the top of the rankings page — three big numbers
   (Rated Players / Tournaments Tracked / Matches Analyzed). Distinct
   namespace from the profile's .hero-stat tree below, which was being
   silently shadowed by the later-declared profile rule. */
.global-stats {
  display: flex;
  align-items: stretch;
  gap: 28px;
  margin-left: auto;
}

.global-stat {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  min-width: 110px;
}

.global-stat__value {
  font-family: var(--font-data);
  font-size: 26px;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.02em;
  line-height: 1;
}

.global-stat__label {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.hero-divider {
  width: 1px;
  align-self: stretch;
  background: var(--border);
}

/* ============================================================
   TOURNAMENTS INDEX — layout rhythm
   Scoped overrides to cap content width, restore hero hierarchy,
   and stack filter concerns vertically so the page has a proper
   heading / controls / table / footer rhythm instead of a single
   undifferentiated slab of rows.
   ============================================================ */

/* Cap the table column at a comfortable reading width on 1440+ screens.
   Below 1280px the rule is a no-op (max-width kicks in only above the
   cap); above it, the row text stops running the full monitor width. */
.tournaments-index {
  max-width: 1280px;
  margin-inline: auto;
}

/* Hero strip: the title earns real display-size weight; the count
   sits immediately next to it like a dateline ("Tournaments · 799
   rated events"), not stretched to the far edge where it floats
   disconnected. The shared .section-header default is space-between
   (leaderboard pairs title with a right-aligned control); on this
   page the count is a supporting stat for the title, so flush-start. */
.tournaments-index .section-header {
  justify-content: flex-start;
  align-items: baseline;
  gap: var(--space-md);
  margin-top: var(--space-xl);
  margin-bottom: var(--space-xl);
}

.section-header__title {
  font-family: var(--font-display);
  font-size: 1.75rem;
  font-weight: 700;
  color: var(--text-primary);
  line-height: 1.1;
  letter-spacing: -0.01em;
}

.section-header__meta {
  margin: 0;
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--text-tertiary);
}

.section-header__count {
  font-family: var(--font-data);
  font-size: 14px;
  font-weight: 600;
  color: var(--text-secondary);
  letter-spacing: 0.01em;
}

/* (filtered) is a link to clear every filter in one shot. The dotted
   underline appears only on hover so the default state reads as a quiet
   status marker, not a blue web link. Chrome becomes functionality. */
.section-header__filtered {
  font-family: var(--font-data);
  font-size: 11px;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-left: var(--space-2xs);
  text-decoration: none;
  border-bottom: 1px dotted transparent;
  transition: border-color 150ms ease;
}

a.section-header__filtered:hover,
a.section-header__filtered:focus-visible {
  border-bottom-color: color-mix(in oklch, var(--accent) 60%, transparent);
  outline: none;
}

/* Search input wrap — holds the field and the `/` keyboard-shortcut
   badge. Position: relative so the badge can absolute-position at the
   right edge without knocking the input's own padding. The badge stays
   out of the way of typed input via right-side padding on the input. */
.search-input-wrap {
  position: relative;
  width: 100%;
  max-width: 480px;
}

.search-input-wrap .search-input {
  width: 100%;
  padding-right: 36px;
}

.search-input__hint {
  position: absolute;
  top: 50%;
  right: 10px;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  font-family: var(--font-data);
  font-size: 11px;
  font-weight: 600;
  color: var(--text-tertiary);
  background: color-mix(in oklch, var(--border) 60%, transparent);
  border: 1px solid var(--border);
  border-radius: 4px;
  pointer-events: none;
  opacity: 0.8;
  transition: opacity 150ms ease, color 150ms ease;
}

.search-input-wrap:focus-within .search-input__hint {
  opacity: 0;
}

/* Hide the hint on small screens — mobile users don't have a keyboard
   and the badge would just eat input padding. */
@media (max-width: 640px) {
  .search-input__hint { display: none; }
  .search-input-wrap .search-input { padding-right: 16px; }
}


/* Filter stack — search + two labeled groups stacked vertically.
   Related rows sit 12px apart; the whole stack separates from the
   table below by a generous 32px so the table reads as a distinct
   block with real whitespace above and below it. */
.filter-stack {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  margin-bottom: var(--space-xl);
}

.filter-stack__search .search-input {
  width: 100%;
  max-width: 480px;
}

.filter-stack__group {
  display: flex;
  align-items: center;
  gap: var(--space-md);
}

.filter-stack__label {
  font-family: var(--font-data);
  font-size: 11px;
  font-weight: 600;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  min-width: 56px;
}

/* Row height matches DESIGN.md spec for TournamentRow (52px).
   The shared .rank-row base is 56px for the leaderboard where the
   rating number wants more presence; tournaments are a denser list
   and earn the 4px back. Also adds an inter-column gap so adjacent
   cells (Players/Winner, Winner/Date, Tier/Format) don't collide —
   numeric and text values had been butting up against each other
   at the cell boundary with no visual breath. Header matches so
   column labels stay perfectly aligned with row cells. Mobile
   override below restores the tighter 2-line card gaps so the
   compact card layout keeps its density. */
.tournaments-index .tournament-row,
.tournaments-index .table-header {
  gap: var(--space-md);
}

.tournaments-index .tournament-row {
  height: 52px;
}

/* Mobile: release the fixed 52px desktop height so the 2-3 line wrap
   card can grow to fit its content. The base .tournament-row mobile
   rule (below, in the main responsive block) sets height: auto too,
   but this scoped selector has higher specificity and wins — without
   this override, long winner usernames overflow the row and collide
   with the next card's title. Gaps pulled in here so the whole mobile
   behavior for tournaments-index is visible in one place. */
@media (max-width: 640px) {
  .tournaments-index .tournament-row {
    height: auto;
    row-gap: 6px;
    column-gap: 10px;
  }
}

/* Pagination breathing room — reads as a page footer, not as row 51. */
.tournaments-index .pagination {
  padding-top: var(--space-xl);
  margin-top: var(--space-sm);
}

/* Small-screen stack: the filter-stack__group wraps its label above
   the chip row so chips still get a full horizontal scroll lane.
   Mobile table-header sticky offset is handled elsewhere. */
@media (max-width: 640px) {
  .filter-stack__group {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-2xs);
  }
  .tournaments-index .section-header {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-2xs);
    margin-top: var(--space-lg);
    margin-bottom: var(--space-lg);
  }
  .section-header__title {
    font-size: 1.5rem;
  }
}

/* ============================================================
   FILTER ROW (search + chips) — legacy, still used elsewhere
   ============================================================ */

.filter-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;
}

.filter-row .search-input {
  width: 480px;
  max-width: 480px;
}

.filter-chips {
  display: flex;
  gap: 8px;
  align-items: center;
}

.chip {
  display: inline-flex;
  align-items: center;
  padding: 6px 16px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background-color: var(--card);
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 500;
  color: var(--text-secondary);
  cursor: pointer;
  transition: all 0.15s ease;
  white-space: nowrap;
}

.chip:hover {
  border-color: var(--accent);
  color: var(--text-primary);
}

.chip--active {
  border-color: var(--accent);
  background-color: var(--accent);
  color: var(--bg);
  font-weight: 600;
}

/* Tier-colored chip variants. Inactive state uses the tier hue for text +
   hover border; active state fills with the tier color (matching the same
   tier's badge on the tournament rows below). */
.chip--tier-planetary { color: var(--tier-planetary); }
.chip--tier-planetary:hover { border-color: var(--tier-planetary); color: var(--tier-planetary); }
.chip--tier-planetary.chip--active { background-color: var(--tier-planetary); border-color: var(--tier-planetary); color: var(--bg); }

.chip--tier-sector { color: var(--tier-sector); }
.chip--tier-sector:hover { border-color: var(--tier-sector); color: var(--tier-sector); }
.chip--tier-sector.chip--active { background-color: var(--tier-sector); border-color: var(--tier-sector); color: var(--bg); }

.chip--tier-regional { color: var(--tier-regional); }
.chip--tier-regional:hover { border-color: var(--tier-regional); color: var(--tier-regional); }
.chip--tier-regional.chip--active { background-color: var(--tier-regional); border-color: var(--tier-regional); color: var(--bg); }

.chip--tier-galactic { color: var(--tier-galactic); }
.chip--tier-galactic:hover { border-color: var(--tier-galactic); color: var(--tier-galactic); }
.chip--tier-galactic.chip--active { background-color: var(--tier-galactic); border-color: var(--tier-galactic); color: var(--bg); }

/* ============================================================
   SEARCH INPUT
   ============================================================ */

.search-input {
  display: block;
  padding: 0 16px;
  background-color: var(--input);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  font-family: var(--font-body);
  font-size: 16px;
  color: var(--text-primary);
  outline: none;
  transition: border-color 0.15s ease;
  height: 44px;
}

.search-input::placeholder { color: var(--text-tertiary); }
.search-input:focus { border-color: var(--accent); }

/* ============================================================
   TABLE CONTAINER (flex-based rows, not <table>)
   Matches Pencil RankRow / TournRow components
   ============================================================ */

.table-container {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.table-header {
  display: flex;
  align-items: center;
  height: 40px;
  padding: 0 20px;
  font-family: var(--font-data);
  font-size: 11px;
  font-weight: 500;
  color: var(--text-tertiary);
  letter-spacing: 0.5px;
  text-transform: uppercase;
  /* Sticks directly below the fixed site nav (56px desktop, 52px mobile) so
     column labels survive scrolls past rank ~15. Background matches --bg so
     the header doesn't render transparent when the sticky kicks in. Mobile
     top offset is handled in the <=640px breakpoint below. */
  position: sticky;
  top: 56px;
  z-index: 10;
  background: var(--bg);
}

@media (max-width: 640px) {
  .table-header { top: 52px; }
}

/* Profile pages already have their own sticky header (.profile-sticky) in
   the same vertical slot — stacking another sticky layer under it just
   obscures the column labels. Drop the sticky behavior here; profile
   tables are paginated to 10 rows so the column labels are rarely
   scrolled out of view anyway. */
.profile-page .table-header {
  position: static;
  top: auto;
}

/* Rank row (leaderboard) */
.rank-row {
  display: flex;
  align-items: center;
  height: 56px;
  padding: 0 20px;
  background: var(--card);
  border-radius: 6px;
  text-decoration: none;
  transition: background 0.1s ease;
  color: inherit;
}

.rank-row:hover { background: var(--card-hover); }

.rank-row--empty {
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 4px;
  height: auto;
  min-height: 72px;
  padding: 16px 20px;
  color: var(--text-tertiary);
  font-size: 13px;
  text-align: center;
}

.rank-row--empty:hover { background: var(--card); }

.rank-row--empty__headline {
  margin: 0;
  color: var(--text-secondary);
  font-weight: 500;
}

.rank-row--empty__recovery {
  margin: 0;
  font-size: 12px;
  color: var(--text-tertiary);
}

.rank-row--empty__link {
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px dotted color-mix(in oklch, var(--accent) 40%, transparent);
  transition: border-color 150ms ease;
}

.rank-row--empty__link:hover,
.rank-row--empty__link:focus-visible {
  border-bottom-color: var(--accent);
  outline: none;
}

/* On desktop, .rank-meta and .tourn-meta are invisible to layout — their
   children participate in the row's flex container directly, matching the
   table-header column widths. On mobile they collapse into a second row. */
.rank-meta, .tourn-meta { display: contents; }

/* Tournament row (profile) */
.tourn-row {
  display: flex;
  align-items: center;
  height: 52px;
  padding: 0 20px;
  background: var(--card);
  border-radius: 6px;
}

/* Column widths — rank table.
   Rank column sized to fit 5 digits at 16px Geist Mono Bold (~48px content)
   plus right-side breathing room before the player name starts. Right-aligned
   so numbers stay visually flush as digit count changes. */
.th-rank, .rank-num    { width: 72px; padding-right: 16px; text-align: right; }
.th-player, .rank-player { flex: 1; min-width: 0; }
.th-rating, .rank-rating { width: 80px; text-align: right; }
.th-record, .rank-record { width: 70px; text-align: center; }
.th-winrate, .rank-winrate { width: 60px; text-align: center; }
.th-events, .rank-events { width: 60px; text-align: center; }
.th-confidence, .rank-confidence { width: 90px; text-align: right; }

/* Column widths — tournament table */
.th-event, .tourn-event   { flex: 1; }
.th-tier, .tourn-tier     { width: 100px; text-align: center; }
.th-delta, .tourn-delta   { width: 80px; text-align: right; }
.th-date, .tourn-date     { width: 90px; text-align: right; }
.tourn-record             { width: 80px; text-align: center; }
.tourn-rating             { width: 80px; text-align: right; }

/* Global tournaments index columns — reuses .rank-row for the row chrome.
   Winner cell is left-aligned so the gold ★ markers stack into a clean
   podium line down the column instead of drifting around a center point
   as usernames change length. Tier/Format stay center-aligned because
   the badge and tag read as centered chips; Players/Date stay right
   because they're numeric/temporal. */
.th-format, .tourn-format   { width: 80px; text-align: center; font-family: var(--font-data); font-size: 11px; color: var(--text-tertiary); text-transform: uppercase; letter-spacing: 0.4px; }
.th-players, .tourn-players { width: 72px; text-align: right; font-family: var(--font-data); font-size: 13px; color: var(--text-secondary); }
.th-winner, .tourn-winner   { width: 140px; text-align: left; }

/* Winner cell repeats on every row — glow here would debase the "accent glow
   means rating hero / #1 rank / Galactic tier badge" signal (see DESIGN.md
   glow-restraint principle). Color alone carries the link affordance; row
   hover raises the row background for the interactive feedback. A dotted
   underline fills in on precision-hover, matching the inline-link idiom
   used by .rank-row--empty__link — rewards the user who aimed at the name. */
.tourn-winner__name {
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  color: var(--accent);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: inline-block;
  max-width: calc(100% - 20px);
  vertical-align: middle;
  border-bottom: 1px dotted transparent;
  transition: border-color 200ms ease, color 150ms ease;
}

.tourn-winner__name:hover,
.tourn-winner__name:focus-visible {
  border-bottom-color: color-mix(in oklch, var(--accent) 60%, transparent);
  outline: none;
}

/* Gold star before the winner name. Scope is the single event, so the
   winner IS the #1 of that event — same rank-gold token used for the
   overall leaderboard's gold medal. One glyph, screen-reader hidden,
   so the density stays tight and the cell still reads as a player link. */
.tourn-winner__medal {
  display: inline-block;
  margin-right: 5px;
  font-size: 11px;
  color: var(--rank-gold);
  vertical-align: baseline;
  line-height: 1;
  pointer-events: none;
  user-select: none;
}

.tourn-winner__empty {
  font-family: var(--font-data);
  font-size: 13px;
  color: var(--text-tertiary);
}

/* Stretched-link pattern: the tournament name is the primary link for the
   row, but its ::before overlay covers the whole card so clicking any
   empty cell still navigates. Other row links (like the winner name) use
   .stretched-link-escape to sit above the overlay and keep their own href. */
.tournament-row {
  position: relative;
  cursor: pointer;
}

.tournament-row .stretched-link::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: auto;
}

.tournament-row .stretched-link-escape {
  position: relative;
  z-index: 1;
}

.tournament-row .tourn-event-name {
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 500;
  color: var(--text-primary);
}

/* Rank number medals */
.rank-num {
  font-family: var(--font-data);
  font-size: 16px;
  font-weight: 700;
  color: var(--text-secondary);
}
.rank--gold   { color: var(--rank-gold); }
.rank--silver { color: var(--rank-silver); }
.rank--bronze { color: var(--rank-bronze); }

/* Player cell with avatar */
.rank-player {
  display: flex;
  align-items: center;
  gap: 12px;
}

.player-avatar {
  width: 34px;
  height: 34px;
  border-radius: 17px;
  background: var(--border);
  flex-shrink: 0;
}

.player-name {
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
}

.player-username {
  font-size: 11px;
  font-weight: 400;
  color: var(--text-tertiary);
  margin-left: 4px;
}

/* Rating column */
.rank-rating {
  font-family: var(--font-data);
  font-size: 13px;
  font-weight: 700;
  color: var(--accent);
}

/* Record, win rate, events */
.rank-record, .tourn-record {
  font-family: var(--font-data);
  font-size: 13px;
  color: var(--text-secondary);
}

.rank-winrate {
  font-family: var(--font-data);
  font-size: 13px;
}

/* Win-rate sign tints — pulled out of an inline style so the view stays
   CSP-friendly and the color semantic lives with the rest of the type.
   The neutral variant renders on zero-match ranked players (rare data
   edge) where "0.0%" in red would falsely imply a losing record. */
.rank-winrate--positive { color: var(--positive); }
.rank-winrate--negative { color: var(--negative); }
.rank-winrate--neutral  { color: var(--text-tertiary); }

.rank-events {
  font-family: var(--font-data);
  font-size: 13px;
  color: var(--text-secondary);
}


/* Confidence badge */
.confidence-badge {
  font-family: var(--font-data);
  font-size: 13px;
  color: var(--text-secondary);
  cursor: help;
  border-bottom: 1px dotted var(--text-tertiary);
}

/* Sortable column header on the tournaments index (Date). Inherits the
   table-header typography so it reads as part of the row; the arrow is
   the only visual signal that the column is interactive. */
.th-date__sort {
  color: inherit;
  text-decoration: none;
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
}

.th-date__sort:hover .th-date__arrow,
.th-date__sort:focus-visible .th-date__arrow {
  color: var(--accent);
}

.th-date__sort:focus-visible {
  outline: 1px solid color-mix(in oklch, var(--accent) 50%, transparent);
  outline-offset: 2px;
  border-radius: 3px;
}

.th-date__arrow {
  color: var(--text-tertiary);
  font-size: 12px;
  transition: color 150ms ease;
}

/* Tournament row specifics */
.tourn-event-name {
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
}

.tourn-event-external {
  font-family: var(--font-data);
  font-size: 10px;
  color: var(--text-tertiary);
  text-decoration: none;
  margin-left: 8px;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  transition: color 150ms ease;
  white-space: nowrap;
}

/* Event location as a dim second line under the event name. Search matches
   location server-side, so surfacing it here is how the row tells the user
   "that 'Milwaukee' you typed? matched this." Inter body font keeps it as
   narrative context; Geist Mono would misread as a data field. */
.tourn-event__location {
  display: block;
  margin-top: 2px;
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--text-tertiary);
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Same location string in the tournament show-page hero meta strip —
   sits inline with tier/format/date/player-count. Uses the meta row's
   existing typography scale; no new tokens introduced. Mirrors the index
   ellipsis cap so an unusually long upstream location string can't blow
   out the meta row on mobile; full string still accessible via Melee. */
.tournament-hero__location {
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--text-tertiary);
  max-width: 32ch;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tourn-event-external:hover {
  color: var(--accent);
}

.tourn-event-external::after {
  content: " \2192";
}

/* On the index row, the "→" glyph is hidden at rest (50 rows × an arrow
   would read as chrome) and fades in only on hover or keyboard focus.
   The link still opens Melee in a new tab; the arrow just surfaces as
   an "external" affordance once the user's cursor declares intent. */
.tournament-row .tourn-event-external::after {
  opacity: 0;
  display: inline-block;
  transition: opacity 150ms ease;
}

.tournament-row .tourn-event-external:hover::after,
.tournament-row .tourn-event-external:focus-visible::after {
  opacity: 1;
}

/* Keyboard focus ring — the winner-name link next door gets implicit
   focus via the browser default; this link deserves the same visibility
   so keyboard users can see where Tab landed above the stretched-link
   overlay. Matches the focus treatment used on other accent links. */
.tournament-row .tourn-event-external:focus-visible {
  outline: 1px solid color-mix(in oklch, var(--accent) 60%, transparent);
  outline-offset: 2px;
  border-radius: 3px;
  color: var(--accent);
}

.tourn-date {
  font-family: var(--font-data);
  font-size: 11px;
  color: var(--text-tertiary);
}

.format-label {
  font-family: var(--font-data);
  font-size: 11px;
  color: var(--text-tertiary);
  margin-left: 4px;
}

.tourn-rating {
  font-family: var(--font-data);
  font-size: 13px;
  font-weight: 700;
  color: var(--accent);
}

/* ============================================================
   BADGES (tier indicators — matches Pencil Tag components)
   ============================================================ */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  border-radius: 4px;
  font-family: var(--font-data);
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
  line-height: 1;
}

.badge--planetary      { color: var(--tier-planetary); background: rgba(34, 197, 94, 0.2); }
.badge--store_showdown { color: var(--text-secondary); background: rgba(148, 163, 184, 0.15); }
.badge--sector         { color: var(--tier-sector);    background: rgba(245, 158, 11, 0.2); }
.badge--regional       { color: var(--tier-regional);  background: rgba(14, 165, 233, 0.2); }
.badge--galactic       { color: var(--tier-galactic);  background: rgba(124, 58, 237, 0.2); }

/* ============================================================
   BREADCRUMB (profile page)
   ============================================================ */

.breadcrumb {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 24px;
}

.breadcrumb-link {
  font-size: 13px;
  color: var(--accent);
}

.breadcrumb-sep {
  font-size: 13px;
  color: var(--text-tertiary);
}

.breadcrumb-current {
  font-size: 13px;
  color: var(--text-secondary);
}

/* ============================================================
   PROFILE NAME
   ============================================================ */

.profile-name {
  font-family: var(--font-display);
  font-size: 32px;
  font-weight: 700;
  color: var(--text-primary);
  margin-bottom: 8px;
}

.profile-name a {
  color: inherit;
}

.profile-name a:hover {
  color: var(--accent);
}

.profile-username {
  font-family: var(--font-data);
  font-size: 16px;
  font-weight: 400;
  color: var(--text-tertiary);
}

.profile-meta {
  display: flex;
  align-items: center;
  gap: 12px;
}

.rank-badge {
  font-family: var(--font-data);
  font-size: 11px;
  font-weight: 600;
  color: var(--text-secondary);
  background: var(--card);
  border: 1px solid var(--border);
  padding: 2px 8px;
  border-radius: 4px;
  letter-spacing: 0.02em;
}

.rank-badge--unranked {
  color: var(--text-tertiary);
}

/* Format qualifier appended to the rank (e.g. "Rank #1 Premier"). Slightly
   softer than the rank number itself so "#1" stays the headline and
   "Premier" reads as context. Uses currentColor inheritance so it tints
   through on gold/silver/bronze medal badges. */
.rank-badge__qualifier {
  font-weight: 400;
  opacity: 0.72;
}

/* Podium medals for ranks 1-3. The design system already defines the tokens
   (DESIGN.md §Rank medals) and the leaderboard table uses them via inline
   case. Only #1 earns a glow — silver and bronze are color-only so the
   accent budget stays reserved for gold. */
.rank-badge--gold {
  color: var(--rank-gold);
  border-color: color-mix(in oklch, var(--rank-gold) 45%, var(--border));
  box-shadow: 0 0 12px color-mix(in oklch, var(--rank-gold) 18%, transparent);
}

.rank-badge--silver {
  color: var(--rank-silver);
}

.rank-badge--bronze {
  color: var(--rank-bronze);
}

/* Compact variant for the per-format ranks inside the hero stat strip.
   Sits as its own line below the ±RD note so the format's headline rating
   stays the dominant element, but the rank gets the same badge treatment
   as the Overall rank chip above the hero. */
.rank-badge--format {
  align-self: flex-start;
  margin-top: 4px;
  font-size: 10px;
  padding: 2px 6px;
}


/* ============================================================
   PROFILE HERO — name + rank + dominant rating + stat-strip,
   all in one card so a player's vitals read as a single unit.
   ============================================================ */

.profile-hero {
  display: grid;
  grid-template-columns: 1fr;
  gap: 18px;
  padding: 18px 22px 20px;
  margin-bottom: 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
}

.profile-hero__top {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
}

.profile-hero__id {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.profile-hero__rank { display: inline-flex; }

.profile-hero__rating {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
  text-align: right;
  flex-shrink: 0;
}

.profile-hero__label {
  font-family: var(--font-data);
  font-size: 11px;
  font-weight: 500;
  color: var(--text-tertiary);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.profile-hero__number {
  font-family: var(--font-data);
  font-size: 48px;
  font-weight: 700;
  color: var(--accent);
  line-height: 1;
  text-shadow: 0 0 16px var(--accent-glow);
  letter-spacing: -0.02em;
}

.profile-hero__number--muted {
  font-family: var(--font-data);
  font-size: 36px;
  color: var(--text-secondary);
  text-shadow: none;
  letter-spacing: normal;
}

.profile-hero__conf {
  font-family: var(--font-data);
  font-size: 12px;
  color: var(--text-tertiary);
}

.profile-hero__conf.confidence-badge {
  border-bottom: 1px dotted var(--text-tertiary);
}

/* Last-event pill. Reads like a stock ticker: sign + magnitude carries the
   whole message. Subordinate to the rating number but louder than the
   confidence % that sits above it — 13px vs 11px — because "what just moved"
   is the primary persona's job-to-be-done. Clicking deep-links to the
   per-tournament audit view. */
.profile-hero__delta {
  display: inline-flex;
  align-items: baseline;
  gap: 0;
  margin-top: 6px;
  font-family: var(--font-data);
  font-size: 13px;
  font-weight: 600;
  font-feature-settings: "tnum";
  line-height: 1;
  text-decoration: none;
  letter-spacing: 0.01em;
}

.profile-hero__delta:hover { filter: brightness(1.15); }

.profile-hero__delta--up    { color: var(--positive); }
.profile-hero__delta--down  { color: var(--negative); }
.profile-hero__delta--flat  { color: var(--text-tertiary); }

.profile-hero__delta-format {
  color: var(--text-secondary);
  font-weight: 500;
}

.profile-hero__delta-sep {
  color: var(--text-tertiary);
  font-weight: 400;
}

/* Context line — tournament name + date. Truncates long event names so the
   hero never wraps past two lines. The full name is available on hover via
   the link's title attribute. */
.profile-hero__delta-meta {
  display: block;
  max-width: 240px;
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--font-body);
  font-size: 11px;
  color: var(--text-tertiary);
  text-align: right;
}

.profile-hero__delta-meta-link {
  color: var(--text-secondary);
  text-decoration: none;
}

.profile-hero__delta-meta-link:hover { color: var(--accent); }

/* Stat-strip lives inside the hero card under the big rating. Tabular
   mono numerals so columns of digits line up between players. Top divider
   reads as a horizontal rule between the hero and the stat row. */
.profile-hero__stats {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 12px 18px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}

.hero-stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.hero-stat__label {
  font-family: var(--font-data);
  font-size: 10px;
  font-weight: 500;
  color: var(--text-tertiary);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.hero-stat__value {
  font-family: var(--font-data);
  font-size: 15px;
  font-weight: 600;
  color: var(--text-primary);
  font-feature-settings: "tnum";
  line-height: 1.1;
}

.hero-stat__value--muted {
  color: var(--text-tertiary);
  font-weight: 400;
}

.hero-stat__note {
  font-family: var(--font-data);
  font-size: 10px;
  color: var(--text-tertiary);
}

@media (max-width: 768px) {
  .profile-hero { padding: 14px 16px 16px; }
  .profile-hero__number { font-size: 40px; }
  .profile-hero__stats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ============================================================
   PER-PLAYER PER-TOURNAMENT AUDIT HERO
   ============================================================ */

.audit-hero {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  padding-bottom: 20px;
  margin-bottom: 20px;
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}

.audit-hero__title { flex: 1; min-width: 0; }

.audit-hero__meta {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 8px;
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--text-tertiary);
}

.audit-hero__date { color: var(--text-secondary); }
.audit-hero__record .data { color: var(--text-primary); font-weight: 600; }

.audit-hero__delta {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-shrink: 0;
}

.audit-hero__rating {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
}

.audit-hero__label {
  font-family: var(--font-data);
  font-size: 10px;
  font-weight: 500;
  color: var(--text-tertiary);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.audit-hero__number {
  font-family: var(--font-data);
  font-size: 32px;
  font-weight: 700;
  color: var(--accent);
  line-height: 1;
  letter-spacing: -0.02em;
}

/* ============================================================
   METRIC STRIP — demoted format ratings + stats
   ============================================================ */

.metric-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 12px 20px;
  margin-bottom: 32px;
  padding: 4px 0;
}

.metric-strip__item {
  display: flex;
  align-items: baseline;
  gap: 8px;
  white-space: nowrap;
}

.metric-strip__label {
  font-family: var(--font-data);
  font-size: 11px;
  font-weight: 500;
  color: var(--text-tertiary);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.metric-strip__value {
  font-family: var(--font-data);
  font-size: 16px;
  font-weight: 600;
  color: var(--text-primary);
}

.metric-strip__value--warning { color: var(--warning); }

.metric-strip__note {
  font-family: var(--font-data);
  font-size: 11px;
  color: var(--text-tertiary);
}

.metric-strip__sep {
  width: 1px;
  height: 16px;
  background: var(--border);
  align-self: center;
}

/* ============================================================
   SECTION HEADER
   ============================================================ */

.section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
  margin-top: 32px;
}

.heading-lg {
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 600;
  color: var(--text-primary);
}

/* ============================================================
   PAGINATION
   ============================================================ */

.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding-top: 16px;
}

.page-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 36px;
  height: 36px;
  border-radius: 6px;
  background: var(--card);
  border: 1px solid var(--border);
  font-family: var(--font-data);
  font-size: 13px;
  color: var(--text-secondary);
  text-decoration: none;
  transition: all 0.15s ease;
}

.page-btn:hover {
  border-color: var(--accent);
  color: var(--text-primary);
}

.page-btn--active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--bg);
  font-weight: 600;
}

.page-dots {
  color: var(--text-tertiary);
  font-size: 13px;
}

/* ============================================================
   FOOTER NOTE
   ============================================================ */

.footer-note {
  font-family: var(--font-data);
  font-size: 11px;
  color: var(--text-tertiary);
  text-align: center;
  padding-top: 12px;
  margin-top: 20px;
}

/* ============================================================
   ABOUT / HOW IT WORKS PAGE
   ============================================================ */

.about-page { max-width: 1200px; margin: 0 auto; }

.about-title {
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 700;
  color: var(--text-primary);
  margin-bottom: 16px;
  letter-spacing: -0.01em;
}

/* System Health callout — the clamp-rate receipt, pulled up to the top of
   the page so the system's self-check is visible before the reader commits
   to 2,400 words of methodology. Mono numerals, tertiary framing, one
   dominant percentage with a tooltip for the raw counts. */
.about-health {
  display: grid;
  grid-template-columns: auto auto 1fr;
  gap: 16px 20px;
  align-items: baseline;
  padding: 14px 18px;
  margin-bottom: 40px;
  background: color-mix(in oklch, var(--accent) 6%, var(--card));
  border: 1px solid color-mix(in oklch, var(--accent) 22%, var(--border));
  border-radius: 8px;
  max-width: 68ch;
}

.about-health__label {
  font-family: var(--font-data);
  font-size: 10px;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.about-health__value {
  font-family: var(--font-data);
  font-size: 20px;
  font-weight: 700;
  color: var(--accent);
  font-feature-settings: "tnum";
  cursor: help;
}

.about-health__desc {
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.6;
  grid-column: 1 / -1;
}

.about-health__desc strong { color: var(--text-primary); }

@media (max-width: 768px) {
  .about-health {
    grid-template-columns: auto 1fr;
  }
  .about-health__label { grid-column: 1; }
  .about-health__value { grid-column: 2; justify-self: end; }
}

/* Two-column layout on desktop: sticky TOC left, main content right. Mobile
   drops back to single column and the TOC is hidden — deep-linking from
   tooltips still works via the anchor IDs on each section. */
.about-layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: 32px;
}

.about-content { min-width: 0; max-width: 800px; }

.about-toc { display: none; }

@media (min-width: 1024px) {
  .about-layout {
    grid-template-columns: 220px minmax(0, 1fr);
    gap: 48px;
  }
  .about-toc {
    display: block;
    position: sticky;
    top: 80px;
    align-self: start;
    max-height: calc(100vh - 100px);
    overflow-y: auto;
  }
}

.about-toc-heading {
  font-family: var(--font-data);
  font-size: 10px;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin: 0 0 12px;
}

.about-toc-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.about-toc-list a {
  display: block;
  padding: 5px 10px;
  font-family: var(--font-data);
  font-size: 12px;
  color: var(--text-secondary);
  text-decoration: none;
  border-radius: 4px;
  transition: color 150ms ease, background-color 150ms ease;
}

.about-toc-list a:hover {
  color: var(--accent);
  background: color-mix(in oklch, var(--accent) 8%, transparent);
}

.about-toc-list a:focus-visible {
  outline: 1px solid color-mix(in oklch, var(--accent) 50%, transparent);
  outline-offset: 2px;
}

/* Anchor-jump offset so clicked section headings land below the sticky
   site nav (56px desktop, 52px mobile) instead of hiding behind it.
   Vertical rhythm between sections lives here too. */
.about-section {
  scroll-margin-top: 80px;
  margin-bottom: 48px;
}

/* H3 subheading used when an H2 section has internal structure — e.g. the
   three components of Event-Weighted K-Factor. Smaller than .about-heading,
   same display font, visible hierarchy without the extra padding of a new
   section break. */
.about-subheading {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 600;
  color: var(--text-primary);
  margin: 32px 0 10px;
  letter-spacing: -0.01em;
}

.about-intro {
  font-size: 16px;
  color: var(--text-secondary);
  line-height: 1.7;
  margin-bottom: 20px;
  max-width: 68ch;
}

.about-intro:last-of-type { margin-bottom: 40px; }

.about-intro strong { color: var(--text-primary); }

/* Second intro beat — the technical sentence for the analyst persona who
   skipped the first-timer welcome. Slightly quieter so the welcoming
   first beat stays dominant. */
.about-intro--technical {
  font-size: 15px;
  color: var(--text-tertiary);
}

.about-intro--technical strong { color: var(--text-secondary); }

.about-heading {
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: 12px;
}

.about-text {
  font-size: 16px;
  color: var(--text-secondary);
  line-height: 1.7;
  margin-bottom: 16px;
  max-width: 68ch;
}

.about-text strong { color: var(--text-primary); }
.about-text a { color: var(--accent); }
.about-text--muted { color: var(--text-tertiary); font-size: 13px; margin-top: 12px; }

/* Inline accent link used in prose paragraphs (changelog, about-intro). */
.inline-link {
  color: var(--accent);
  border-bottom: 1px solid transparent;
  transition: border-color 150ms ease, color 150ms ease;
}
.inline-link:hover {
  color: var(--accent-hover);
  border-bottom-color: var(--accent-hover);
}

/* Info cards */
.about-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
}

.about-card-row {
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
}

.about-card-row:last-child { border-bottom: none; }

.about-card-label {
  font-family: var(--font-data);
  font-size: 11px;
  font-weight: 500;
  color: var(--text-tertiary);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: 6px;
}

.about-card-value {
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 700;
  color: var(--text-primary);
  margin-bottom: 4px;
  letter-spacing: -0.01em;
}

.about-card-desc {
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.6;
}

/* Numbered factors */
.about-factors {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.about-factor {
  display: flex;
  gap: 16px;
  align-items: flex-start;
}

.about-factor-num {
  width: 36px;
  height: 36px;
  border-radius: 8px;
  background: var(--card);
  border: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-data);
  font-size: 13px;
  font-weight: 700;
  color: var(--text-primary);
  flex-shrink: 0;
}

/* Format-code tints for the P/L/E factor chips in the Formats section.
   Each uses the tier color as background with white text for contrast. */
.about-factor-num--sector   { background: var(--tier-sector); border-color: var(--tier-sector); color: #fff; }
.about-factor-num--regional { background: var(--tier-regional); border-color: var(--tier-regional); color: #fff; }
.about-factor-num--galactic { background: var(--tier-galactic); border-color: var(--tier-galactic); color: #fff; }

.about-factor-content { flex: 1; }

.about-factor-content h3 {
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: 4px;
}

.about-factor-content p {
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.6;
  max-width: 68ch;
}

/* Tier/round tables */
.about-table {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
}

.about-table-header {
  display: flex;
  padding: 10px 20px;
  font-family: var(--font-data);
  font-size: 11px;
  font-weight: 500;
  color: var(--text-tertiary);
  letter-spacing: 0.5px;
  text-transform: uppercase;
  border-bottom: 1px solid var(--border);
}

.about-table-row {
  display: flex;
  padding: 12px 20px;
  align-items: center;
  border-bottom: 1px solid var(--border);
}

.about-table-row:last-child { border-bottom: none; }

.about-table-col-tier { width: 140px; flex-shrink: 0; }
.about-table-col-val { width: 100px; flex-shrink: 0; font-weight: 600; color: var(--accent); }

/* Highlighted multiplier values — replaces inline style="color: var(--warning);"
   on the Putting-It-All-Together rows that call out finals-winner totals. */
.about-table-col-val--highlight { color: var(--warning); }
.about-table-col-val--champion  { color: var(--warning); font-weight: 700; }

/* The single "Galactic Finals (champion)" callout row — the one match worth
   the most in the system. Warm tint + slightly heavier border to match its
   semantic weight. Replaces an inline background style. */
.about-table-row--champion {
  background: color-mix(in oklch, var(--warning) 8%, transparent);
}

/* Labeled-list modifier tints for the Qualifying Events card. Replaces
   inline color styles on the Included / Excluded labels. */
.about-card-label--positive { color: var(--positive); }
.about-card-label--muted    { color: var(--text-tertiary); }
.about-table-col-desc { flex: 1; font-size: 13px; color: var(--text-secondary); }

/* Worked example — the one place on the page where the math is walked
   end-to-end instead of stated as a formula. Stepped numbered blocks
   so the reader can follow the order of operations visually. */
.about-example {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 24px;
}

.about-example__setup {
  font-size: 14px;
  color: var(--text-secondary);
  line-height: 1.7;
  margin: 0 0 24px;
  padding-bottom: 20px;
  border-bottom: 1px solid var(--border);
}

.about-example__steps {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.about-example__step {
  display: flex;
  gap: 16px;
  align-items: flex-start;
}

.about-example__step-num {
  width: 28px;
  height: 28px;
  border-radius: 14px;
  background: color-mix(in oklch, var(--accent) 18%, var(--card));
  border: 1px solid color-mix(in oklch, var(--accent) 35%, var(--border));
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-data);
  font-size: 12px;
  font-weight: 700;
  color: var(--accent);
  flex-shrink: 0;
  margin-top: 1px;
}

.about-example__step-body { flex: 1; min-width: 0; }

.about-example__step-heading {
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
  margin: 0 0 4px;
  letter-spacing: -0.005em;
}

.about-example__step-body p {
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.7;
  margin: 0;
}

.about-example__step-body code {
  font-family: var(--font-data);
  font-size: 12px;
  background: color-mix(in oklch, var(--accent) 10%, transparent);
  color: var(--text-primary);
  padding: 1px 5px;
  border-radius: 3px;
}

/* ============================================================
   CHANGELOG — reverse-chronological entry list with sticky version
   sidebar. Shares the .content-area.about-page wrapper with how-it-works
   and inherits .about-title / .about-intro typography.
   ============================================================ */

.changelog-layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: 32px;
}

@media (min-width: 1024px) {
  .changelog-layout {
    grid-template-columns: 180px minmax(0, 1fr);
    gap: 48px;
  }
  .changelog-toc {
    position: sticky;
    top: 80px;
    align-self: start;
    max-height: calc(100vh - 100px);
    overflow-y: auto;
  }
}

.changelog-toc { display: none; }
@media (min-width: 1024px) { .changelog-toc { display: block; } }

.changelog-toc__heading {
  font-family: var(--font-data);
  font-size: 10px;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin: 0 0 12px;
}

.changelog-toc__list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.changelog-toc__link {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  padding: 6px 10px;
  border-radius: 4px;
  text-decoration: none;
  color: var(--text-secondary);
  transition: color 150ms ease, background-color 150ms ease;
}

.changelog-toc__link:hover {
  color: var(--accent);
  background: color-mix(in oklch, var(--accent) 8%, transparent);
}

.changelog-toc__link:focus-visible {
  outline: 1px solid color-mix(in oklch, var(--accent) 50%, transparent);
  outline-offset: 2px;
}

.changelog-toc__version {
  font-family: var(--font-data);
  font-size: 13px;
  font-weight: 600;
}

.changelog-toc__date {
  font-family: var(--font-data);
  font-size: 10px;
  color: var(--text-tertiary);
}

.changelog-toc__link--current .changelog-toc__version {
  color: var(--accent);
}

.changelog-content { min-width: 0; max-width: 800px; }

.changelog-entries {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.changelog-entry {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 20px 24px 24px;
  scroll-margin-top: 80px;
  transition: border-color 150ms ease;
}

.changelog-entry:hover {
  border-color: color-mix(in oklch, var(--accent) 20%, var(--border));
}

.changelog-entry:target,
.changelog-entry--current {
  border-color: color-mix(in oklch, var(--accent) 40%, var(--border));
}

.changelog-entry:target .changelog-entry__permalink,
.changelog-entry:hover .changelog-entry__permalink {
  opacity: 1;
}

.changelog-entry__header {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 12px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
}

.changelog-entry__meta {
  display: flex;
  align-items: baseline;
  gap: 10px;
}

.changelog-entry__version {
  font-family: var(--font-data);
  font-size: 18px;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.01em;
}

/* Current version gets the accent color as the signal. No glow — glow is
   reserved for the rating hero, #1 rank, table rating cells, and the
   Galactic tier badge (see DESIGN.md glow-restraint principle). The
   paired "Live" tag on the same row carries the freshness signal. */
.changelog-entry--current .changelog-entry__version {
  color: var(--accent);
}

.changelog-entry__date {
  font-family: var(--font-data);
  font-size: 11px;
  color: var(--text-tertiary);
  letter-spacing: 0.04em;
}

.changelog-entry__badges {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-left: auto;
}

/* Small tags categorizing each change. "Rating change" is positive-tinted
   because that's the signal a player cares about when scanning the list.
   Engine / Display are neutral. "Live" is the top-version marker. */
.changelog-entry__tag {
  font-family: var(--font-data);
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 3px 8px;
  border-radius: 3px;
  border: 1px solid currentColor;
  white-space: nowrap;
}

.changelog-entry__tag--rating {
  color: var(--positive);
  background: color-mix(in oklch, var(--positive) 10%, transparent);
}

.changelog-entry__tag--engine {
  color: var(--text-secondary);
  background: transparent;
}

.changelog-entry__tag--display {
  color: var(--text-tertiary);
  background: transparent;
}

.changelog-entry__tag--current {
  color: var(--accent);
  background: color-mix(in oklch, var(--accent) 12%, transparent);
  border-color: color-mix(in oklch, var(--accent) 40%, var(--border));
}

.changelog-entry__permalink {
  font-family: var(--font-data);
  font-size: 16px;
  font-weight: 400;
  color: var(--text-tertiary);
  text-decoration: none;
  opacity: 0;
  transition: opacity 150ms ease, color 150ms ease;
  padding: 0 4px;
}

.changelog-entry__permalink:hover {
  opacity: 1;
  color: var(--accent);
}

/* Keyboard focus: reveal the glyph AND show a visible ring so the tab
   stop is discoverable. Matches the :focus-visible pattern used by
   `.th-date__sort` and `.about-faq-q` elsewhere in this file. */
.changelog-entry__permalink:focus-visible {
  opacity: 1;
  color: var(--accent);
  outline: 1px solid color-mix(in oklch, var(--accent) 60%, transparent);
  outline-offset: 2px;
  border-radius: 3px;
}

.changelog-entry__body {
  font-size: 14px;
  line-height: 1.7;
  color: var(--text-secondary);
}

.changelog-entry__headline {
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 600;
  color: var(--text-primary);
  margin: 0 0 10px;
  letter-spacing: -0.005em;
}

.changelog-entry__prose {
  margin: 0;
}

.changelog-entry__prose code {
  font-family: var(--font-data);
  font-size: 12px;
  background: color-mix(in oklch, var(--accent) 8%, transparent);
  color: var(--text-primary);
  padding: 1px 5px;
  border-radius: 3px;
}

/* Mobile: tags stack below the version+date row when screen is narrow */
@media (max-width: 640px) {
  .changelog-entry__badges { margin-left: 0; }
  .changelog-entry__permalink { display: none; }
}

/* FAQ — native <details> disclosures. Collapsed by default so the 8-item
   block reads as a scannable index of questions; clicking any one opens
   just that answer. No JS, no ARIA, no state management. */
.about-faq {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0;
  margin-bottom: 8px;
  transition: border-color 150ms ease;
}

.about-faq[open] {
  border-color: color-mix(in oklch, var(--accent) 35%, var(--border));
}

.about-faq-q {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 16px 20px;
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 600;
  color: var(--text-primary);
  cursor: pointer;
  list-style: none;
  transition: color 150ms ease;
}

.about-faq-q::-webkit-details-marker { display: none; }

.about-faq-q::after {
  content: "+";
  margin-left: auto;
  font-family: var(--font-data);
  font-size: 18px;
  font-weight: 400;
  color: var(--text-tertiary);
  transition: transform 200ms ease, color 150ms ease;
}

.about-faq[open] .about-faq-q::after {
  content: "\2212"; /* minus sign */
  color: var(--accent);
}

.about-faq-q:hover { color: var(--accent); }

.about-faq-q:focus-visible {
  outline: 1px solid color-mix(in oklch, var(--accent) 50%, transparent);
  outline-offset: -1px;
  border-radius: 8px;
}

.about-faq-a {
  padding: 0 20px 18px;
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.7;
  margin: 0;
}

.about-faq-a a { color: var(--accent); }

/* ============================================================
   RESPONSIVE
   ============================================================ */

@media (max-width: 1024px) {
  .content-area { padding: 24px 32px 32px; }
  .hero-section { padding: 36px 32px 28px; gap: 20px 28px; }
  .hero-logo { height: 112px; }
  .hero-title { font-size: 32px; }
  .hero-sub { font-size: 14px; }
  .global-stats { gap: 20px; margin-left: 0; }
  .global-stat__value { font-size: 20px; }
  .global-stat { min-width: 80px; }
  .rank-confidence, .th-confidence { display: none; }
  .filter-row .search-input { width: 320px; max-width: 320px; }
}

@media (max-width: 640px) {
  .content-area { padding: 20px 16px 24px; }
  .hero-section { padding: 28px 16px 22px; gap: 18px 20px; flex-direction: column; text-align: center; align-items: center; }
  .hero-logo { height: 96px; }
  .hero-lockup { align-items: center; }
  .hero-title { font-size: 26px; text-align: center; }
  .hero-sub { font-size: 13px; text-align: center; }
  .global-stats { flex-wrap: wrap; justify-content: center; gap: 14px 20px; margin-left: 0; }
  .global-stat { min-width: auto; align-items: center; }
  .global-stat__value { font-size: 18px; }
  .hero-divider { display: none; }

  .filter-row {
    flex-direction: column;
    align-items: stretch;
  }
  .filter-row .search-input { width: 100%; max-width: none; }
  .filter-chips { flex-wrap: wrap; }

  /* Hide desktop column headers on mobile — rows use stacked layout instead */
  .table-header .th-record,
  .table-header .th-winrate,
  .table-header .th-events,
  .table-header .th-confidence,
  .table-header .th-tier,
  .table-header .th-date,
  .table-header .th-format,
  .table-header .th-players,
  .table-header .th-winner,
  .table-header .th-delta { display: none; }

  /* Leaderboard row becomes a 2-line card */
  .rank-row {
    flex-wrap: wrap;
    height: auto;
    min-height: 64px;
    padding: 10px 16px;
    row-gap: 6px;
    column-gap: 12px;
  }
  /* Mobile: left-align so rank hugs the left edge and sits naturally before
     the player name. Wider than desktop's 72px isn't needed here since the
     row-gap of the wrapping flex keeps rank and name separated. 56px fits
     5 digits at 16px Geist Mono Bold with a touch of room. */
  .rank-num { width: 56px; padding-right: 8px; text-align: left; }
  .rank-player { flex: 1; min-width: 0; }
  .rank-rating { width: auto; text-align: right; }

  .rank-meta {
    display: flex;
    flex-basis: 100%;
    align-items: baseline;
    gap: 12px;
    font-size: 11px;
    color: var(--text-tertiary);
  }
  .rank-meta > span {
    width: auto;
    text-align: left;
    font-size: 11px;
    color: var(--text-tertiary);
  }
  .rank-meta .rank-winrate { font-weight: 600; }
  .rank-meta .rank-record::before { content: "W-L "; color: var(--text-tertiary); opacity: 0.7; }
  .rank-meta .rank-events::before { content: "Events "; color: var(--text-tertiary); opacity: 0.7; }
  .rank-meta .confidence-badge { font-size: 11px; color: var(--text-tertiary); }

  /* Tournament row becomes a 2-line card */
  .tourn-row {
    flex-wrap: wrap;
    height: auto;
    min-height: 60px;
    padding: 10px 16px;
    row-gap: 6px;
    column-gap: 12px;
    align-items: baseline;
  }
  .tourn-event { flex: 1; min-width: 0; }

  .tourn-meta {
    display: flex;
    flex-basis: 100%;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 6px 12px;
    font-size: 11px;
    color: var(--text-tertiary);
  }
  .tourn-meta > * {
    width: auto;
    text-align: left;
  }
  .tourn-meta .tourn-rating { font-size: 13px; }
  .tourn-meta .tourn-delta { margin-left: auto; }

  /* Tournaments index row (.rank-row.tournament-row): on mobile the event
     name takes a full-width first line, then tier/format/players/winner/
     date wrap beneath as a compact meta strip. Without this, the fixed-
     width columns flow awkwardly and the tier badge jams into the middle
     of a wrapping event name. */
  .tournament-row {
    flex-wrap: wrap;
    height: auto;
    min-height: 68px;
    padding: 10px 16px;
    row-gap: 6px;
    column-gap: 10px;
    align-items: baseline;
  }
  .tournament-row .tourn-event {
    flex-basis: 100%;
    width: 100%;
  }
  .tournament-row .tourn-tier,
  .tournament-row .tourn-format,
  .tournament-row .tourn-players,
  .tournament-row .tourn-winner,
  .tournament-row .tourn-date {
    width: auto;
    text-align: left;
    font-size: 12px;
  }
  .tournament-row .tourn-format,
  .tournament-row .tourn-players,
  .tournament-row .tourn-date {
    color: var(--text-tertiary);
  }
  .tournament-row .tourn-winner { margin-left: auto; }
  .tournament-row .tourn-players::after { content: " players"; opacity: 0.7; }

  .profile-hero {
    flex-direction: column;
    align-items: flex-start;
    gap: 16px;
  }
  .profile-hero__rating {
    align-items: flex-start;
    text-align: left;
  }
  .profile-hero__number { font-size: 40px; }
  .profile-hero__number--muted { font-size: 30px; }
  .profile-hero__delta-meta { text-align: left; }

  .metric-strip { gap: 8px 16px; }
  .metric-strip__sep { display: none; }

  .site-nav { padding: 0 16px; height: 52px; }
  .site-logo { font-size: 16px; }
  .nav-logo-img { height: 32px; }
}

/* ============================================================
   v3 — Trust layer: cohort toggle, RD bands, credible interval
   ============================================================ */

/* Secondary filter row — sits below the format chips and search */
.filter-row--secondary {
  margin-top: 12px;
  margin-bottom: 8px;
}

/* Overall format is experimental — visually muted so players prefer per-format */
.chip--experimental {
  opacity: 0.75;
  font-style: italic;
}

.chip--experimental.chip--active { opacity: 1; font-style: normal; }

/* Ranked / Provisional cohort toggle */
.cohort-toggle {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--card);
  padding: 4px;
}

.cohort-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  border-radius: 4px;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 500;
  color: var(--text-tertiary);
  cursor: pointer;
  transition: all 0.15s ease;
}

.cohort-chip:hover { color: var(--text-primary); }

.cohort-chip--active {
  background: var(--accent-surface);
  color: var(--accent);
  font-weight: 600;
}

.cohort-count {
  font-family: var(--font-data);
  font-size: 11px;
  color: var(--text-tertiary);
  background: var(--bg);
  padding: 1px 6px;
  border-radius: 10px;
  min-width: 18px;
  text-align: center;
}

.cohort-chip--active .cohort-count {
  background: rgba(14, 165, 233, 0.18);
  color: var(--accent);
}

/* Rating cell — number inherits typography from .rank-rating parent;
   only .rank-rating__ci below needs its own override for the smaller,
   dimmer ± credible-interval span. The .rank-row--provisional override
   further down still targets .rank-rating__number by class name to
   desaturate the number in provisional rows. */
.rank-rating__ci {
  font-family: var(--font-data);
  font-size: 11px;
  font-weight: 400;
  color: var(--text-tertiary);
  margin-left: 6px;
  cursor: help;
}

/* Provisional row — visually quieter on the ranked leaderboard if one slips
   in, and always on the Provisional tab. 0.82 was almost imperceptible
   against the already-dim palette; 0.65 actually reads as "still stabilizing"
   at a glance. Accent color loses its glow treatment. Hover restores to full
   so the row is still scannable on intent. */
.rank-row--provisional { opacity: 0.65; }
.rank-row--provisional .rank-rating__number { color: var(--text-secondary); }
.rank-row--provisional:hover { opacity: 1; }

/* ============================================================
   STYLED TOOLTIPS — replaces native title="" on data/help elements.
   Usage: <span class="has-tooltip" data-tooltip="Full sentence here">78%</span>
   Supports an optional position hint via data-tooltip-pos="left|right|bottom".
   Default anchor: above the element, center-aligned.
   ============================================================ */

.has-tooltip {
  position: relative;
  cursor: help;
}

.has-tooltip::before,
.has-tooltip::after {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease, transform 0.15s ease;
  z-index: 300;
}

/* Tooltip body */
.has-tooltip::after {
  content: attr(data-tooltip);
  bottom: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  background: #0F172A;
  border: 1px solid var(--border);
  color: var(--text-primary);
  padding: 10px 14px;
  border-radius: 6px;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 400;
  line-height: 1.55;
  letter-spacing: 0.005em;
  text-align: left;
  text-transform: none;
  width: max-content;
  max-width: 320px;
  white-space: normal;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.55);
}

/* Caret */
.has-tooltip::before {
  content: "";
  bottom: calc(100% + 4px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  border: 6px solid transparent;
  border-top-color: var(--border);
  width: 0;
  height: 0;
}

.has-tooltip:hover::before,
.has-tooltip:hover::after,
.has-tooltip:focus-visible::before,
.has-tooltip:focus-visible::after {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* Right-anchor variant — for tooltips near the left edge */
.has-tooltip[data-tooltip-pos="right"]::after,
.has-tooltip[data-tooltip-pos="right"]::before {
  left: auto;
  right: 0;
  transform: translateX(0) translateY(4px);
}
.has-tooltip[data-tooltip-pos="right"]::before { right: 10px; }
.has-tooltip[data-tooltip-pos="right"]:hover::after,
.has-tooltip[data-tooltip-pos="right"]:hover::before { transform: translateX(0) translateY(0); }

/* Left-anchor variant — for tooltips near the right edge (leaderboard Confidence column) */
.has-tooltip[data-tooltip-pos="left"]::after,
.has-tooltip[data-tooltip-pos="left"]::before {
  left: 0;
  right: auto;
  transform: translateX(0) translateY(4px);
}
.has-tooltip[data-tooltip-pos="left"]::before { left: 10px; }
.has-tooltip[data-tooltip-pos="left"]:hover::after,
.has-tooltip[data-tooltip-pos="left"]:hover::before { transform: translateX(0) translateY(0); }

/* Bottom-anchor — for tooltips that would clip off the top of the viewport */
.has-tooltip[data-tooltip-pos="bottom"]::after {
  bottom: auto;
  top: calc(100% + 10px);
  transform: translateX(-50%) translateY(-4px);
}
.has-tooltip[data-tooltip-pos="bottom"]::before {
  bottom: auto;
  top: calc(100% + 4px);
  border-top-color: transparent;
  border-bottom-color: var(--border);
  transform: translateX(-50%) translateY(-4px);
}
.has-tooltip[data-tooltip-pos="bottom"]:hover::after,
.has-tooltip[data-tooltip-pos="bottom"]:hover::before { transform: translateX(-50%) translateY(0); }

/* Confidence percentage — leaderboard + profile. Hover reveals raw RD.
   Tier colors come from rd_band so a glance still tells you if a rating
   is established/developing/provisional, but the number is the data. */
.confidence-pct {
  display: inline-flex;
  align-items: baseline;
  font-family: var(--font-data);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--text-secondary);
  cursor: help;
}

.confidence-pct--established { color: var(--positive); }
.confidence-pct--developing  { color: var(--warning); }
.confidence-pct--provisional { color: var(--text-tertiary); }

/* RD-band badges — retained for any lingering view usage */
.band-badge {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 10px;
  border: 1px solid transparent;
  cursor: help;
}

.band-badge--established {
  color: var(--positive);
  background: rgba(34, 197, 94, 0.08);
  border-color: rgba(34, 197, 94, 0.25);
}

.band-badge--developing {
  color: var(--warning);
  background: rgba(245, 158, 11, 0.08);
  border-color: rgba(245, 158, 11, 0.25);
}

.band-badge--provisional {
  color: var(--text-tertiary);
  background: rgba(148, 163, 184, 0.08);
  border-color: rgba(148, 163, 184, 0.2);
}

/* Provisional banner on profile pages */
.provisional-banner {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 16px;
  margin-bottom: 20px;
  background: rgba(245, 158, 11, 0.06);
  border: 1px solid rgba(245, 158, 11, 0.25);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font-size: 13px;
  line-height: 1.5;
}

.provisional-banner strong { color: var(--warning); font-weight: 600; }

/* Calm informational banner — tiny data, separate-format context, etc.
   Accent-blue tint instead of the warning-amber provisional banner. */
.format-notice {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 8px;
  padding: 10px 16px;
  margin-bottom: 20px;
  background: rgba(14, 165, 233, 0.05);
  border: 1px solid rgba(14, 165, 233, 0.22);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font-size: 13px;
  line-height: 1.5;
}

.format-notice strong {
  color: var(--accent);
  font-weight: 600;
}

/* Plain-English explainer inside each tournament dropdown on the profile page.
   Answers the community question "why did I get 0 points / so few points at
   a big tournament?" The label sits above the sentence in Geist Mono caps
   so it reads as a data row header, not a generic blurb. */
.tourn-explainer {
  margin-bottom: 16px;
  padding: 12px 16px;
  background: rgba(14, 165, 233, 0.06);
  border-left: 2px solid var(--accent);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

.tourn-explainer__label {
  display: block;
  font-family: var(--font-data);
  font-size: 10px;
  font-weight: 600;
  color: var(--accent);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: 4px;
}

.tourn-explainer__text {
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-secondary);
}

/* Small persistent caption explaining the leaderboard sort order. Community
   feedback: players kept asking "why is Bobby above FAME when FAME has a
   higher rating?" — because we sort by the lower bound of the 95% CI, not
   the raw number. Caption lives right above the table so it's in scope
   whenever someone is scanning ranks. */
.sort-caption {
  font-size: 12px;
  color: var(--text-tertiary);
  margin: 6px 0 14px;
  line-height: 1.5;
}

.sort-caption code {
  font-family: var(--font-data);
  font-size: 12px;
  color: var(--text-secondary);
  background: none;
  padding: 0;
}

.sort-caption a {
  color: var(--text-secondary);
  border-bottom: 1px dotted currentColor;
  text-decoration: none;
}

.sort-caption a:hover { color: var(--accent); }

/* Admin surfaces (anomaly review, etc). Intentionally understated — these
   aren't end-user pages, so we lean on the same table/form primitives as
   the main app rather than building a second visual language. */
.admin-count {
  font-family: var(--font-data);
  font-size: 12px;
  color: var(--text-tertiary);
}

.admin-filter-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
  align-items: flex-end;
  margin: 12px 0 20px;
  padding: 12px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}

.admin-filter-row label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--text-tertiary);
}

.admin-filter-row input,
.admin-filter-row select {
  font-family: var(--font-data);
  font-size: 13px;
  color: var(--text-primary);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 6px 8px;
  min-width: 110px;
}

.admin-filter-row button {
  border: none;
  cursor: pointer;
  padding: 7px 14px;
}

/* Tournament detail page ─────────────────────────────────────────────── */

.tournament-hero {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 24px;
  flex-wrap: wrap;
  padding: 20px 0 16px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 20px;
}

.tournament-hero__title h1 {
  margin: 0 0 10px;
}

.tournament-hero__meta {
  display: flex;
  align-items: center;
  gap: 8px 12px;
  flex-wrap: wrap;
}

.tournament-hero__date,
.tournament-hero__count {
  font-family: var(--font-data);
  font-size: 12px;
  color: var(--text-tertiary);
}

.tournament-hero__winner {
  display: flex;
  flex-direction: column;
  gap: 2px;
  text-align: right;
}

.tournament-hero__winner-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-tertiary);
}

.tournament-hero__winner-name {
  font-family: var(--font-data);
  font-size: 18px;
  font-weight: 700;
  color: var(--accent);
  text-shadow: 0 0 12px rgba(14, 165, 233, 0.35);
}

/* Actual bracket: Quarters → Semis → Finals, left to right. Each round is
   its own flexbox column with justify-content: space-around so matches
   stay vertically centered relative to what feeds them. Horizontal
   connector lines extend from every non-final match into the next column. */

.tournament-bracket {
  display: flex;
  align-items: stretch;
  gap: 40px;
  margin-bottom: 32px;
  padding: 4px 12px 12px;
}

.bracket-column {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1;
}

.bracket-column__label {
  font-family: var(--font-data);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-tertiary);
  text-align: center;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 16px;
}

.bracket-column__matches {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  gap: 8px;
}

.bracket-match {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}

/* Horizontal connector extending rightward from every match in all
   columns except the last. Puts a tick-mark that reads as a bracket
   feed without requiring pairing metadata we don't have. */
.bracket-column:not(:last-child) .bracket-match::after {
  content: '';
  position: absolute;
  left: 100%;
  top: 50%;
  width: 40px;
  border-top: 1px solid var(--border);
}

/* Horizontal connector extending leftward into every match after the
   first column, meeting the outgoing line from the previous round. */
.bracket-column:not(:first-child) .bracket-match::before {
  content: '';
  position: absolute;
  right: 100%;
  top: 50%;
  width: 40px;
  border-top: 1px solid var(--border);
}

.bracket-match__player {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 4px 8px;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  font-family: var(--font-body);
  font-size: 13px;
}

.bracket-match__player a {
  color: inherit;
}

.bracket-match__player--winner {
  background: rgba(14, 165, 233, 0.08);
  color: var(--text-primary);
  font-weight: 600;
}

.bracket-match__score {
  font-family: var(--font-data);
  font-size: 12px;
  color: var(--text-tertiary);
}

.bracket-match__player--winner .bracket-match__score {
  color: var(--accent);
  font-weight: 700;
}

/* Responsive fallback: stack columns on narrow viewports. Connectors hide
   since they only make sense horizontally. */
@media (max-width: 768px) {
  .tournament-bracket {
    flex-direction: column;
    gap: 20px;
  }
  .bracket-column:not(:last-child) .bracket-match::after,
  .bracket-column:not(:first-child) .bracket-match::before {
    display: none;
  }
}

/* Tournament rating-shift table — reuses .rank-row and the table-header
   column classes. Adds two scoped column widths: 'Before' (pre-tournament
   rating) and a variant RD cell that drops the confidence-pill styling. */
.th-shift-before, .shift-before {
  width: 80px;
  text-align: right;
  font-family: var(--font-data);
  font-size: 13px;
  color: var(--text-tertiary);
}

.shift-row .shift-rd {
  font-family: var(--font-data);
  font-size: 13px;
  color: var(--text-tertiary);
  font-weight: 500;
}

/* Rating history chart — dark panel with a fixed height so the Chart.js
   canvas has somewhere to draw. No border beyond the container frame,
   the grid lines carry the structure. */
.rating-chart-wrap {
  height: 220px;
  padding: 12px 12px 6px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  margin-bottom: 24px;
}

.rating-chart { display: block; width: 100% !important; height: 100% !important; }

/* Head-to-head table — uses shared .table-container + .rank-row primitives,
   with a per-row left border vibe tint and a compact win/draw/loss split
   bar that carries the record visually. */
.th-h2h-record, .h2h-record   { width: 80px; text-align: center; font-family: var(--font-data); font-size: 13px; color: var(--text-secondary); }
.th-h2h-viz, .h2h-viz         { width: 110px; text-align: center; }
.th-h2h-winrate, .h2h-winrate { width: 70px; text-align: right; font-family: var(--font-data); font-size: 13px; }
.th-h2h-matches, .h2h-matches { width: 72px; text-align: right; font-family: var(--font-data); font-size: 13px; color: var(--text-secondary); }

.h2h-rating-fmt {
  font-family: var(--font-data);
  font-size: 10px;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.4px;
  margin-left: 6px;
}

/* Left accent border vibes — green for favored matchups, red for nemesis.
   4px strip so the aesthetic stays restrained (no full-row tinting). */
.h2h-row { border-left: 3px solid transparent; }
.h2h-row--favorable { border-left-color: var(--positive); }
.h2h-row--nemesis   { border-left-color: var(--negative); }
.h2h-row--even      { border-left-color: var(--border); }

.h2h-row--favorable .h2h-winrate { color: var(--positive); font-weight: 600; }
.h2h-row--nemesis   .h2h-winrate { color: var(--negative); font-weight: 600; }

/* Split bar: one flex row showing wins/draws/losses as proportional
   segments. Colored by outcome. Total width fixed by the column. */
.h2h-viz__bar {
  display: flex;
  align-items: stretch;
  width: 88px;
  height: 8px;
  border-radius: 4px;
  overflow: hidden;
  background: rgba(148, 163, 184, 0.12);
  margin: 0 auto;
}
.h2h-viz__win  { background: var(--positive); }
.h2h-viz__draw { background: var(--warning); opacity: 0.7; }
.h2h-viz__loss { background: var(--negative); }

/* ─── H2H inline expansion (details panel under each rival row) ─── */

/* Panel shell — matches .tourn-expand so the H2H expansion and the
   Tournament History expansion read as the same surface grammar. */
.h2h-expand {
  background: var(--surface);
  border: 1px solid var(--border);
  border-top: none;
  border-bottom-left-radius: 6px;
  border-bottom-right-radius: 6px;
  overflow: hidden;
}

/* Hero row inside the expansion: horizontal split bar on the left
   (the rivalry at a glance), big win rate on the right (the headline
   number). Mirrors the hero density pattern from the profile. */
.h2h-expand__hero {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 16px 20px 12px;
  border-bottom: 1px solid rgba(148, 163, 184, 0.08);
  flex-wrap: wrap;
}
.h2h-expand__hero-main { flex: 1; min-width: 240px; }

.h2h-expand__hero-winrate {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
}
.h2h-expand__hero-winrate .h2h-vibe { margin-left: 0; margin-bottom: 2px; }
.h2h-expand__hero-winrate .audit-hero__label {
  font-size: 10px;
  letter-spacing: 1.2px;
}
.h2h-expand__hero-winrate .audit-hero__number {
  font-family: var(--font-data);
  font-size: 26px;
  color: var(--accent);
  font-feature-settings: "tnum";
  line-height: 1;
}

.h2h-vibe {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 1.2px;
  padding: 2px 8px;
  margin-left: 10px;
  border-radius: 3px;
  border: 1px solid currentColor;
  text-transform: uppercase;
}
.h2h-vibe--favorable { color: var(--positive); }
.h2h-vibe--nemesis   { color: var(--negative); }
.h2h-vibe--even      { color: var(--text-tertiary); }

/* Horizontal split bar under the hero — proportional win/draw/loss
   breakdown visible at a glance. Reuses the tokens from the profile
   H2H aggregate row's viz for consistency. */
.h2h-hero__split {
  margin-top: 14px;
  max-width: 520px;
}
.h2h-hero__split-bar {
  display: flex;
  height: 10px;
  border-radius: 5px;
  overflow: hidden;
  background: rgba(148, 163, 184, 0.1);
}
.h2h-hero__split-bar > span { display: block; transition: width 200ms ease; }
.h2h-hero__split-bar .split--win  { background: var(--positive); }
.h2h-hero__split-bar .split--draw { background: var(--warning); opacity: 0.7; }
.h2h-hero__split-bar .split--loss { background: var(--negative); }

.h2h-hero__split-legend {
  display: flex;
  gap: 18px;
  margin-top: 8px;
  font-family: var(--font-data);
  font-size: 11px;
  color: var(--text-tertiary);
  letter-spacing: 0.3px;
  text-transform: uppercase;
}
.h2h-hero__split-legend > span::before {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  margin-right: 6px;
  vertical-align: middle;
}
.h2h-hero__split-legend .legend--win::before  { background: var(--positive); }
.h2h-hero__split-legend .legend--draw::before { background: var(--warning); }
.h2h-hero__split-legend .legend--loss::before { background: var(--negative); }

/* H2H match table: overrides .tourn-matches grid (which is sized for the
   7-column audit view) with column priorities tuned for this page:
   tournament wide (it's the point), rating pills compact. Selector doubles
   up to beat .tourn-matches source-order specificity. */
.tourn-matches.h2h-match-table {
  display: grid;
  width: 100%;
  grid-template-columns:
    96px     /* Date */
    minmax(240px, 1fr)  /* Tournament — the scan anchor */
    56px     /* Round */
    72px     /* Format */
    86px     /* Player rating */
    86px     /* Opponent rating */
    72px;    /* Result */
  padding: 0 20px 16px;
}

.tourn-matches.h2h-match-table .tourn-matches__header > span {
  font-size: 10px;
  padding: 12px 0 10px;
}

/* Header "Date" aligns with row date values — rows carry 12px left
   padding for the outcome stripe, so the header's first cell has to
   match or the column labels look off. */
.tourn-matches.h2h-match-table .tourn-matches__header > span:first-child {
  padding-left: 15px;
}

/* Player name headers — mono + primary color so the two competitors
   read as column subjects, not dimmed labels. No truncation: when the
   name is longer than the column, it ellipsizes inline. */
.h2h-match-table__name-col {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-primary) !important;
  letter-spacing: 0.3px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Per-row outcome accent — 3px left stripe on the first cell of each
   match row. display:contents parent means we can't box-shadow the
   whole row, so we stripe the first span and pad it. Color = outcome,
   matches site-wide grammar. */
.tourn-matches.h2h-match-table .h2h-match-row > span {
  padding: 12px 0;
  border-bottom: 1px solid rgba(148, 163, 184, 0.08);
  align-self: center;
}
.tourn-matches.h2h-match-table .h2h-match-row:last-child > span { border-bottom: none; }

.tourn-matches.h2h-match-table .h2h-match-row > span:first-child {
  padding-left: 12px;
  border-left: 3px solid transparent;
}
.h2h-match-row--win  > span:first-child { border-left-color: var(--positive) !important; }
.h2h-match-row--loss > span:first-child { border-left-color: var(--negative) !important; }
.h2h-match-row--draw > span:first-child { border-left-color: var(--warning)  !important; }

/* Tournament name cell — unconstrained line wrapping off by default,
   so long names truncate gracefully instead of exploding the row. */
.h2h-match-row__tourn {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.h2h-match-row__tourn a {
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1;
  min-width: 0;
}
.h2h-match-row__tourn a:hover { color: var(--accent); }

/* Tier chip next to the tournament name — compact, data-dense
   classification without taking a separate column. */
.h2h-match-row__tier {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  padding: 2px 6px;
  border-radius: 2px;
}
.h2h-match-row__tier--planetary { color: var(--positive); border: 1px solid var(--positive); }
.h2h-match-row__tier--sector    { color: var(--warning);  border: 1px solid var(--warning);  }
.h2h-match-row__tier--regional  { color: var(--accent);   border: 1px solid var(--accent);   }
.h2h-match-row__tier--galactic  { color: #A78BFA;         border: 1px solid #A78BFA;          }

/* Date cell — mono, tertiary, single line, right-aligned so numbers
   line up visually across rows. */
.tourn-matches.h2h-match-table .h2h-match-row .h2h-match-row__date {
  font-family: var(--font-data);
  font-size: 11px;
  color: var(--text-tertiary);
  white-space: nowrap;
}

/* Rating pill cells — center the pill so the numbers align across
   the two player rating columns. */
.tourn-matches.h2h-match-table .h2h-match-row > span:nth-child(5),
.tourn-matches.h2h-match-table .h2h-match-row > span:nth-child(6) {
  display: flex;
  justify-content: center;
  align-items: center;
}

@media (max-width: 768px) {
  .tourn-matches.h2h-match-table {
    grid-template-columns: auto 1fr 72px;
    padding: 0 12px;
  }
  .tourn-matches.h2h-match-table .h2h-match-row > span:nth-child(n+3):nth-child(-n+6) {
    display: none;
  }
  .tourn-matches.h2h-match-table .tourn-matches__header > span:nth-child(n+3):nth-child(-n+6) {
    display: none;
  }
}

/* ─── Profile sticky header + section nav ─── */
.profile-sticky {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  padding: 10px 0;
  margin-bottom: 20px;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
  backdrop-filter: blur(6px);
}

/* Kill the breadcrumb's own bottom margin when it's inside the sticky row —
   the sticky row already handles vertical rhythm. */
.profile-sticky .breadcrumb { margin-bottom: 0; }

.profile-section-nav {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
}

.profile-section-nav__link {
  font-family: var(--font-data);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--text-tertiary);
  padding: 5px 10px;
  border-radius: 5px;
  border: 1px solid transparent;
  text-decoration: none;
  transition: border-color 150ms ease, color 150ms ease;
}

.profile-section-nav__link:hover {
  color: var(--accent);
  border-color: var(--accent);
}

/* Anchored section targets get scroll-margin so clicks land below the
   sticky bar instead of having the heading tucked behind it. */
.section-anchor {
  scroll-margin-top: 72px;
}

/* Smooth scroll for in-page anchor jumps */
html { scroll-behavior: smooth; }

/* Styled horizontal rule between major profile sections (Rating History,
   Tournament History, Head-to-Head). Subtle accent highlight in the middle
   so it reads as a data-terminal section break, not a default gray line. */
.profile-section-divider {
  height: 0;
  margin: 36px 0;
  border: 0;
  border-top: 1px solid var(--border);
  background: transparent;
  position: relative;
}

.profile-section-divider::after {
  content: "";
  position: absolute;
  top: -1px;
  left: 50%;
  transform: translateX(-50%);
  width: 72px;
  height: 1px;
  background: var(--accent);
  opacity: 0.6;
}

/* Rating history section — chart wrapper is a block so the canvas height
   behaves. Format chips moved into the unified .profile-format-tabs. */
.rating-history-block { display: block; }
.rating-history-block .section-header { align-items: center; }

/* Empty-state overlay sits dead-center over the canvas when there's no
   data for the selected format. Chart still draws empty axes underneath
   so the layout doesn't reflow on tab switches. */
.rating-chart-wrap { position: relative; }
.rating-chart-empty {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-data);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  pointer-events: none;
  background: linear-gradient(180deg, rgba(11, 17, 32, 0) 0%, rgba(11, 17, 32, 0.55) 50%, rgba(11, 17, 32, 0) 100%);
}

/* ============================================================
   PROFILE FORMAT TABS — single switch driving Rating History,
   Tournament History, and Head-to-Head together. Designed to
   read clearly as a navigation control, not subtle filter chips.
   ============================================================ */

.profile-format-tabs {
  display: flex;
  align-items: stretch;
  gap: 0;
  margin: 0 0 28px;
  padding: 0;
  border-bottom: 1px solid var(--border);
  position: relative;
  flex-wrap: wrap;
}

.profile-format-tab {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 12px 22px;
  margin-bottom: -1px; /* overlap the bottom border so active tab's underline replaces it */
  font-family: var(--font-data);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  text-decoration: none;
  border: 1px solid transparent;
  border-bottom: 2px solid transparent;
  background: transparent;
  cursor: pointer;
  transition: color 150ms ease, border-color 150ms ease, background 150ms ease;
}

.profile-format-tab:hover {
  color: var(--text-primary);
  background: rgba(14, 165, 233, 0.06);
  border-bottom-color: var(--text-tertiary);
}

.profile-format-tab--active {
  color: var(--accent);
  background: linear-gradient(180deg, rgba(14, 165, 233, 0.10) 0%, rgba(14, 165, 233, 0.02) 100%);
  border-bottom-color: var(--accent);
  text-shadow: 0 0 12px var(--accent-glow);
}

.profile-format-tab--active::after {
  content: "";
  position: absolute;
  bottom: -2px;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--accent);
  box-shadow: 0 0 8px var(--accent-glow);
}

/* Right-side hint that explains the tabs drive every section below.
   Pushed to the right with margin-left:auto so it stays out of the
   way of the tab row but stays informative. */
.profile-format-tabs__hint {
  margin-left: auto;
  align-self: center;
  padding: 0 6px 8px;
  font-family: var(--font-data);
  font-size: 10px;
  color: var(--text-tertiary);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

@media (max-width: 768px) {
  .profile-format-tab { padding: 10px 14px; font-size: 12px; }
  .profile-format-tabs__hint { display: none; }
}

/* ============================================================
   PAGINATION NAV — custom CSS, no Tailwind.
   ============================================================ */

.pagy-nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 6px;
  margin: 20px 0 8px;
  padding: 12px 0 0;
  font-family: var(--font-data);
}

.pagy-nav__link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  height: 32px;
  padding: 0 10px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 5px;
  text-decoration: none;
  transition: border-color 150ms ease, color 150ms ease, background 150ms ease;
}

.pagy-nav__link:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.pagy-nav__link--current {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--bg);
  box-shadow: 0 0 10px var(--accent-glow);
}

.pagy-nav__link--arrow { padding: 0 12px; }

.pagy-nav__link--disabled,
.pagy-nav__link--disabled:hover {
  color: var(--text-tertiary);
  border-color: var(--border);
  background: transparent;
  cursor: not-allowed;
  box-shadow: none;
}

.pagy-nav__gap {
  color: var(--text-tertiary);
  padding: 0 4px;
}

/* "Showing X–Y of Z" sits centered on its own line below the page links.
   `flex-basis: 100%` forces a wrap so the hint never competes with the
   numbered controls for horizontal space. */
.pagy-nav__hint {
  flex-basis: 100%;
  text-align: center;
  margin-top: 8px;
  font-size: 11px;
  color: var(--text-tertiary);
  letter-spacing: 0.04em;
}

/* ============================================================
   H2H EMPTY STATE — terminal "no signal" blank slate.
   Direct copy, no emojis, sci-fi data terminal vibe.
   ============================================================ */

.h2h-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 36px 24px 40px;
  background: var(--surface);
  border: 1px dashed var(--border);
  border-radius: 8px;
  text-align: center;
}

.h2h-empty__reticle {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-data);
  color: var(--text-tertiary);
  font-size: 13px;
  letter-spacing: 0.4em;
  text-transform: uppercase;
}

.h2h-empty__bracket {
  color: var(--accent);
  font-size: 18px;
  text-shadow: 0 0 6px var(--accent-glow);
}

.h2h-empty__core {
  position: relative;
}

.h2h-empty__core::after {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-left: 8px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 8px var(--accent-glow);
  vertical-align: middle;
  animation: h2h-pulse 1.8s ease-in-out infinite;
}

@keyframes h2h-pulse {
  0%, 100% { opacity: 0.4; }
  50% { opacity: 1; }
}

.h2h-empty__copy {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-width: 480px;
}

.h2h-empty__headline {
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 600;
  color: var(--text-primary);
}

.h2h-empty__sub {
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--text-tertiary);
  line-height: 1.5;
}

/* Profile hero: credible-interval ± width. Sized to match .profile-hero__conf
   (12px) so neither reads louder than the other — the CI width and the
   confidence % are two views of the same uncertainty signal, and the
   confidence % is the more interpretable of the two, so the CI should
   never visually dominate. */
.profile-hero__ci {
  font-family: var(--font-data);
  font-size: 12px;
  color: var(--text-tertiary);
  font-weight: 400;
  margin-top: 4px;
}

/* Tournament history: expandable per-match audit trail */
.tourn-row-wrapper { display: block; }

.tourn-row { cursor: pointer; }
.tourn-row[aria-expanded="true"] { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }

/* Affordance chevron — sits to the left of every row, points right when
   collapsed and rotates to point down when the <details> is open. The
   native disclosure marker is suppressed so this is the only indicator. */
.tourn-row { list-style: none; }
.tourn-row::-webkit-details-marker { display: none; }

.tourn-row__chevron {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  flex-shrink: 0;
  margin-right: 8px;
  color: var(--text-tertiary);
  transition: transform 150ms ease, color 150ms ease;
}

.tourn-row:hover .tourn-row__chevron { color: var(--accent); }

details[open] > .tourn-row > .tourn-row__chevron,
details[open] > .h2h-row > .tourn-row__chevron {
  transform: rotate(90deg);
  color: var(--accent);
}

/* H2H rows reuse the tourn-row disclosure pattern so the chevron and
   expansion behave identically. The marker is suppressed, the summary
   takes the flex row layout from .rank-row, and the bottom radius
   opens up when the panel expands so the two read as one unit. */
.h2h-row { cursor: pointer; list-style: none; }
.h2h-row::-webkit-details-marker { display: none; }
.h2h-row:hover .tourn-row__chevron { color: var(--accent); }
details[open] > .h2h-row { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }

/* Header alignment column for the chevron — same width + margin as the
   chevron column so the Event header lines up with the event names. */
.th-chevron {
  width: 20px;
  flex-shrink: 0;
  margin-right: 8px;
}

/* Expansion panel — wraps the metric strip + matches grid so the audit
   info lives on the profile directly. Shares surface + border with the
   summary row so the two read as a single expanded unit. */
.tourn-expand {
  background: var(--surface);
  border: 1px solid var(--border);
  border-top: none;
  border-bottom-left-radius: 6px;
  border-bottom-right-radius: 6px;
  overflow: hidden;
}

.tourn-expand__meta {
  padding: 12px 20px;
}

/* Strip chrome off the matches grid when it lives inside an expansion
   panel — the .tourn-expand wrapper already carries the background and
   border. On the audit page it renders standalone with its own shell. */
.tourn-expand .tourn-matches {
  background: transparent;
  border: none;
  border-radius: 0;
  border-top: 1px solid var(--border);
}

/* Inline metric-strip modifier: kill the section-level bottom margin
   and tighten gaps since we're already inside a padded panel. */
.metric-strip--inline {
  margin: 0;
  padding: 0;
  gap: 8px 28px;
}

.tourn-matches {
  background: var(--surface);
  border: 1px solid var(--border);
  border-top: none;
  border-bottom-left-radius: 6px;
  border-bottom-right-radius: 6px;
  padding: 12px 20px;
  font-family: var(--font-data);
  font-size: 12px;
  color: var(--text-secondary);
  display: grid;
  grid-template-columns: 50px 64px 1fr 70px 60px 60px 70px;
  gap: 4px 12px;
  align-items: center;
}

.tourn-matches__header {
  display: contents;
  font-size: 10px;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.4px;
}

.tourn-matches__header > span { padding-bottom: 6px; border-bottom: 1px solid var(--border); }

.tourn-match { display: contents; }
.tourn-match > span { padding: 4px 0; }

.tourn-match__result--win { color: var(--positive); }
.tourn-match__result--loss { color: var(--negative); }
.tourn-match__result--draw { color: var(--warning); }

.tourn-match__mult {
  color: var(--text-tertiary);
  font-size: 11px;
}

.tourn-match__opponent a {
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: 12px;
}

.tourn-match__hri {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Column alignment — shared by profile inline expansion and tournament breakdown.
   Columns: 1 Round (left) | 2 HRI (center) | 3 Opponent (left) |
            4 Result (center) | 5 Game W-L (right) | 6 Multiplier (right) | 7 Type (right) */
.tourn-matches__header > span:nth-child(2),
.tourn-matches__header > span:nth-child(4) {
  text-align: center;
}

.tourn-matches__header > span:nth-child(n+5) {
  text-align: right;
}

.tourn-match > span:nth-child(4) {
  text-align: center;
}

.tourn-match > span:nth-child(n+5) {
  text-align: right;
}

.tourn-match__hri-pill {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  font-family: var(--font-data);
  font-size: 11px;
  font-feature-settings: "tnum";
  color: var(--text-secondary);
  background: rgba(148, 163, 184, 0.06);
  border: 1px solid var(--border);
  border-radius: 10px;
  cursor: help;
  transition: border-color 150ms ease, color 150ms ease;
  white-space: nowrap;
}

.tourn-match__hri-pill:hover {
  color: var(--text-primary);
  border-color: var(--text-tertiary);
}

.tourn-match__hri--none {
  color: var(--text-tertiary);
  font-family: var(--font-data);
  font-size: 11px;
}

@media (max-width: 768px) {
  .tourn-matches {
    grid-template-columns: auto auto 1fr;
    gap: 4px 10px;
  }
  .tourn-matches__header { display: none; }
  .tourn-match > span { font-size: 11px; }
}

/* ============================================================
   FEEDBACK — modal + form + nav button + flash
   ============================================================ */

/* Nav-bar Feedback button: same visual weight as a nav link but styled
   as a button so a11y reads it as an action, not a destination. */
.nav-link--feedback {
  background: transparent;
  border: 1px solid var(--border);
  padding: 4px 12px;
  border-radius: 5px;
  cursor: pointer;
  transition: border-color 150ms ease, color 150ms ease, background 150ms ease;
}
.nav-link--feedback:hover {
  color: var(--accent);
  border-color: var(--accent);
  background: rgba(14, 165, 233, 0.06);
}

/* Right-edge cluster in the sticky header: the section-jump nav plus the
   standalone Report Issue action. The action is NOT inside the <nav>, so
   screen-readers don't announce a modal trigger as a profile section. */
.profile-sticky__tail {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

/* Report Issue — deliberately different from the section-jump anchors so
   a keyboard tabber can tell an action from a jump. Ghost-button styling
   with a hairline border that activates on hover. */
.profile-sticky__report {
  font-family: var(--font-data);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--text-tertiary);
  background: transparent;
  padding: 5px 10px;
  border: 1px solid var(--border);
  border-radius: 5px;
  cursor: pointer;
  transition: border-color 150ms ease, color 150ms ease;
}

.profile-sticky__report:hover,
.profile-sticky__report:focus-visible {
  color: var(--accent);
  border-color: var(--accent);
}

/* Modal — native <dialog> element. Uses the data-terminal aesthetic to
   match the rest of the site. ::backdrop blurs the page underneath.
   `inset: 0; margin: auto` centers horizontally + vertically (Chrome/Edge
   defaults handle this for un-styled <dialog> but we override `display`,
   so we set it explicitly). */
.feedback-modal[open] {
  display: block;
  position: fixed;
  inset: 0;
  margin: auto;
  padding: 0;
  width: min(540px, calc(100vw - 24px));
  max-height: calc(100vh - 48px);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text-primary);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(14, 165, 233, 0.18);
  overflow: hidden;
}

.feedback-modal::backdrop {
  background: rgba(11, 17, 32, 0.72);
  backdrop-filter: blur(4px);
}

.feedback-modal__inner {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 22px 24px 24px;
  max-height: calc(100vh - 48px);
  overflow-y: auto;
}

.feedback-modal__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.feedback-modal__close {
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 5px;
  font-size: 22px;
  line-height: 1;
  color: var(--text-tertiary);
  cursor: pointer;
  transition: border-color 150ms ease, color 150ms ease;
}
.feedback-modal__close:hover {
  color: var(--accent);
  border-color: var(--accent);
}

.feedback-modal__intro {
  margin: 0;
}

/* Form — also used standalone on /feedbacks/new. Tabular, dense, no fluff. */
.feedback-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.feedback-form__row {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.feedback-form__label {
  font-family: var(--font-data);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.feedback-form__hint {
  margin: 6px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--text-tertiary);
}

.feedback-form__hint strong {
  color: var(--text-secondary);
  font-weight: 600;
}

.feedback-form__input,
.feedback-form__textarea {
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--text-primary);
  background: var(--input);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 9px 12px;
  width: 100%;
  transition: border-color 150ms ease, box-shadow 150ms ease;
}

/* Strip the native <select> appearance and draw our own chevron so the
   caret sits at consistent padding, matches the dark theme, and doesn't
   look squashed against the right edge. The SVG inlines a chevron-down. */
select.feedback-form__input {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 36px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'><path d='M1 1.5L6 6.5L11 1.5' stroke='%2394A3B8' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 14px center;
  cursor: pointer;
}

select.feedback-form__input:focus {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'><path d='M1 1.5L6 6.5L11 1.5' stroke='%230EA5E9' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/></svg>");
}

.feedback-form__textarea {
  resize: vertical;
  min-height: 120px;
  line-height: 1.5;
}

.feedback-form__input:focus,
.feedback-form__textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(14, 165, 233, 0.18);
}

.feedback-form__actions {
  display: flex;
  justify-content: flex-end;
}

.feedback-form__errors {
  background: rgba(239, 68, 68, 0.08);
  border: 1px solid rgba(239, 68, 68, 0.4);
  color: var(--negative);
  border-radius: 5px;
  padding: 10px 12px;
  font-size: 13px;
}
.feedback-form__errors ul {
  list-style: disc;
  margin: 6px 0 0 18px;
  padding: 0;
}

/* Generic primary button used by the form submit + future actions. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 9px 18px;
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  border-radius: 5px;
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition: background 150ms ease, border-color 150ms ease, color 150ms ease;
}

.btn--primary {
  background: var(--accent);
  color: var(--bg);
  border-color: var(--accent);
}
.btn--primary:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
  color: var(--bg);
}

/* Toast-style flash anchored bottom-center. Auto-fades after 4s. */
.flash {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  z-index: 100;
  padding: 10px 18px;
  background: var(--surface);
  border: 1px solid var(--accent);
  border-radius: 5px;
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--text-primary);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(14, 165, 233, 0.16);
  animation: flash-fade 4s ease forwards;
}
.flash--notice { color: var(--text-primary); }

@keyframes flash-fade {
  0%, 80% { opacity: 1; transform: translateX(-50%) translateY(0); }
  100%    { opacity: 0; transform: translateX(-50%) translateY(8px); pointer-events: none; }
}

/* ============================================================
   AUTH PAGES — Devise sign in / password reset.
   Centered card, dark theme, brand chrome. Reuses the existing
   .feedback-form__input + .btn primitives.
   ============================================================ */

.auth-page {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: calc(100vh - 120px);
  padding: 32px 16px;
}

.auth-card {
  position: relative;
  width: 100%;
  max-width: 420px;
  padding: 28px 32px 32px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.45), 0 0 0 1px rgba(14, 165, 233, 0.18);
}

/* Same accent edge-glow as the profile hero card. */
.auth-card::before {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: 8px;
  border: 1px solid transparent;
  background: linear-gradient(180deg, rgba(14, 165, 233, 0.22), transparent 50%) border-box;
  -webkit-mask: linear-gradient(#000 0 0) padding-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
}

.auth-card__brand {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 24px;
}

.auth-logo {
  height: 28px;
  width: auto;
}

.auth-card__chip {
  font-family: var(--font-data);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.2em;
  color: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 4px;
  padding: 2px 8px;
  background: rgba(14, 165, 233, 0.08);
  text-shadow: 0 0 8px var(--accent-glow);
}

.auth-card__title {
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 700;
  color: var(--text-primary);
  margin: 0 0 6px;
}

.auth-card__sub {
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--text-tertiary);
  margin: 0 0 20px;
}

.auth-form {
  /* Tighter than the feedback modal — shorter form, more breathing room. */
  gap: 16px;
}

.auth-actions {
  margin-top: 4px;
}

.auth-actions .btn {
  width: 100%;
  justify-content: center;
}

.auth-remember {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--text-tertiary);
  cursor: pointer;
}
.auth-remember input[type="checkbox"] {
  accent-color: var(--accent);
  width: 14px;
  height: 14px;
}

.auth-card__footer {
  margin: 18px 0 0;
  text-align: center;
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--text-tertiary);
}

/* Inline alert for Devise's flash messages (alert/notice). */
.auth-flash {
  margin: 0 0 14px;
  padding: 10px 12px;
  font-family: var(--font-body);
  font-size: 13px;
  border-radius: 5px;
  border: 1px solid var(--border);
  background: var(--input);
  color: var(--text-secondary);
}
.auth-flash--alert {
  color: var(--negative);
  border-color: rgba(239, 68, 68, 0.4);
  background: rgba(239, 68, 68, 0.08);
}
.auth-flash--notice {
  color: var(--accent);
  border-color: rgba(14, 165, 233, 0.4);
  background: rgba(14, 165, 233, 0.08);
}


