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

   The values the table system and the player match table share. The rest of
   the stylesheet still carries its literals; these exist so that the two
   table designs cannot drift apart again. */
:root {
  --lp-text: #363636;
  --lp-text-soft: #4a4a4a;
  /* #7a7a7a came to 4.29:1 on white — under AA for the small text this is
     actually used for: every table header, both table captions, and the stat
     labels on the player page. #6a6a6a is 5.4:1 and reads the same. */
  --lp-text-muted: #6a6a6a;

  --lp-border: #dbdbdb;
  --lp-border-soft: #ededed;

  --lp-surface: #fff;
  --lp-hover: #f5f5f5;

  /* A result is read from its colour first and its letter second, so the two
     tints are the same wherever a row can be won or lost. */
  /* The blue <meta name="theme-color"> already claims. It existed only there;
     the search dropdown's rank badges reached for Bulma's is-info instead, and
     white on that is 3.6:1. */
  --lp-info: #296fa8;

  --lp-win-bg: #effaf5;
  --lp-win-bg-hover: #e3f6ee;
  --lp-win: #257953;
  --lp-loss-bg: #feecf0;
  --lp-loss-bg-hover: #fde0e7;
  --lp-loss: #cc0f35;
  /* The band between the two: a win rate either side of half, and the ranks a
     player climbed. It was drawn in Bulma's amber, which is 1.75:1 on white —
     the least readable thing on the site, on two of its headline numbers.
     Amber dark enough to hold its own against white is necessarily this brown;
     it still reads as the third colour between the green and the red. */
  --lp-mid: #8a6100;

  /* The row the reader came for: his team in a standing, himself in a list. */
  --lp-current-bg: #fffbeb;
  --lp-current-border: #ffc107;

  --lp-radius: 6px;
  --lp-radius-sm: 4px;
}

/* ===== BULMA COLOUR HELPERS, REPOINTED =====

   The site has its own accessible result palette — --lp-win and --lp-loss are
   what the stat boxes and the won/lost match rows are painted with — but the
   tables reached for Bulma's helpers instead, and those are tuned for a tint
   behind them rather than for text on white: is-success is 2.14:1 and
   is-danger 2.8:1, against the 4.5:1 small text needs. The victoires and
   défaites columns of every roster and standing were drawn in them, so the two
   palettes both disagreed with each other and failed on the more used half.

   Repointed here rather than at each of the 20 call sites so the tokens stay
   the one place a result colour is written down; dashboard.html adds
   has-text-success from JS and is covered too. Bulma sets these !important. */
.has-text-success {
  color: var(--lp-win) !important;
}

.has-text-danger {
  color: var(--lp-loss) !important;
}

/* Bulma's grey-light is 2.15:1. It is used here for text that has to be read —
   a club's ID, the "Carrière" and "Bilan" labels over the player charts, the
   "adresse non disponible" fallback — not for decoration. */
.has-text-grey-light {
  color: var(--lp-text-muted) !important;
}

.has-text-warning {
  color: var(--lp-mid) !important;
}

/* The season switcher's unclickable entries — a season this page has no
   counterpart in. Bulma's is-static grey is 4.26:1 on its own grey fill, just
   under AA, and these sit in a row with eight links that read clearly. */
.button.is-static {
  color: var(--lp-text-muted);
}

.header-box {
    background: #f5f5f5;
    color: #363636;
    border: 1px solid #dbdbdb;
    border-radius: 6px;
    padding: 2rem;
    box-shadow: none;
    text-align: center;
  }
  
  .header-box h1 {
    font-weight: 700;
    letter-spacing: 1.5px;
    margin-bottom: 0.5rem;
  }
  
  .header-box p {
    font-weight: 300;
    margin-bottom: 0.2rem;
  }
  
  .wrap-button-text {
    min-height: 64px;
    white-space: inherit;
}

/* Club grid layout - restore original Bulma grid behavior */
.clubs-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 0.75rem;
}

@media screen and (max-width: 768px) {
  .clubs-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media screen and (min-width: 769px) and (max-width: 1023px) {
  .clubs-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media screen and (min-width: 1024px) {
  .clubs-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media screen and (min-width: 1216px) {
  .clubs-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* Club card styles */
.club-card {
  position: relative;
  display: block;
  /* Stretch to the row so a card beside a taller one is not short. */
  height: 100%;
}

/* A grid item will not shrink below its own min-content unless told to, and the
   club button's is about 148px. On a 320px phone the two tracks are 130px each,
   so the cards pushed the grid 27px wider than the page and the whole index
   scrolled sideways. The button wraps its text, so it has somewhere to go. */
.clubs-grid > * {
  min-width: 0;
}

.club-button-container {
  display: block;
}

/* A fixed 64px clipped the longest names once the cards narrowed: "ONEUX
   Alliance Le Congo" wants three lines on a 320-360px phone and lost the
   bottom 5px of the third. min-height keeps every other card the same size it
   was, and the grid row stretches for the one that needs it. */
.club-card .wrap-button-text {
  width: 100%;
  min-height: 64px;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.club-card-star {
  position: absolute;
  top: -17px;
  right: -18px;
  z-index: 10;
  background: transparent !important;
  border: none;
  font-size: 1.1em;
  cursor: pointer;
  /* The glyph is 23x24: too small to hit with a thumb. The padding grows the
     target to ~35px without moving the star, which is why the offsets below
     carry it rather than the -11/-12 the bare glyph needed. It still hangs into
     the section's 24px gutter rather than past the viewport. */
  padding: 6px;
  margin: 0;
  outline: none;
}

.club-card-star:hover {
  color: #ffab00;
}

.club-card-star.star-button.starred {
  color: #ffab00 !important;
}

/* Starred club highlighting */
.club-card.club-starred {
  border: 2px solid #ffc107 !important;
  border-radius: 6px;
}

.club-card .button.club-starred {
  background-color: #fff3cd !important;
  border: none !important;
}

.fixed-column {
  white-space: nowrap;
  width: 1%;
}

.expand-column {
  width: auto;
}

/* Player card styles */
.mobile-player-card {
  position: relative;
}

.mobile-player-card-link {
  display: block;
  text-decoration: none;
  color: inherit;
}

.player-card-star {
  position: absolute;
  top: 8px;
  right: 12px;
  z-index: 1;
}

/* The star is the one thing still out of the flow, so the name row has to be
   told it is there: "TZIKAS LOVREGLIO Alexandros" is 27 characters and would
   otherwise run under it. */
.mobile-player-card .player-name-row {
  padding-right: 2.25rem;
}

/* The licence number, at the end of the card's stats line.
   It used to be positioned absolutely in the bottom-right corner, which took it
   out of the flow while the stats row still filled the card's width. On a 393px
   phone the stats fitted on one line and were printed straight underneath it —
   "% Victoires 89.1%" over "25305". Narrower phones happened to wrap the stats
   and hide it, wider ones happened to leave room, so it only showed in a band
   around the commonest sizes.
   As a flex sibling of the stats it cannot overlap them at any width, and the
   stats wrap only when they genuinely do not fit. Reserving a fixed gutter for
   it instead would have cost every card a second line even where it fitted. */
.lp-card-foot {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 0.75rem;
}

.lp-card-foot .lp-card-stats {
  flex: 1 1 auto;
  min-width: 0;
}

.player-card-id {
  flex: 0 0 auto;
  margin-left: auto;
  white-space: nowrap;
}

/* Starred player highlighting */
.player-starred {
  background-color: #fff3cd !important;
  border: 2px solid #ffc107 !important;
}

/* Star button styles */
.star-button {
  background: white;
  border: none;
  cursor: pointer;
  font-size: 1.3em;
  color: #ccc;
  transition: color 0.2s;
}

.star-button.starred {
  color: #ffc107;
}

.star-button:hover {
  color: #ffab00;
}

/* ===== TABLES =====

   One look for every table on the site. Bulma's own modifiers are deliberately
   not used: `is-bordered`, `is-striped`, `is-hoverable` and `is-narrow` were
   combined five different ways across the ten tables, so the same component
   read differently on each page. `.lp-table` replaces the lot, and takes the
   player match table's language — a quiet header, no cell borders, colour kept
   for what a row means rather than for its parity. */

/* Bulma puts both at `top`, and the project used to override `td` alone with
   an `!important`, which left `th` where it was: a header row mixing the two
   was misaligned by construction. lipong.css loads after Bulma, so equal
   specificity is enough. */
.table td,
.table th {
  vertical-align: middle;
}

/* Centered table */
.table-centered {
  margin-left: auto;
  margin-right: auto;
}

.table.lp-table {
  width: 100%;
  margin-bottom: 0;
  background-color: transparent;
  color: var(--lp-text);
}

/* The header is a label, not a row of data: it names the columns and then gets
   out of the way. Same treatment as the small headings above the stat cards. */
.table.lp-table thead th {
  border: 0;
  border-bottom: 2px solid var(--lp-border);
  background-color: transparent;
  padding: 0.45rem 0.6rem;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--lp-text-muted);
  white-space: nowrap;
  vertical-align: middle;
}

.table.lp-table tbody td {
  border: 0;
  border-bottom: 1px solid var(--lp-border-soft);
  /* Bulma paints every cell opaque; transparent lets the box show through, so
     a row's own colour is the only thing that tints it. */
  background-color: transparent;
  padding: 0.55rem 0.6rem;
  vertical-align: middle;
}

/* The last rule would otherwise draw a line along the bottom of the box. */
.table.lp-table tbody tr:last-child td {
  border-bottom: 0;
}

.table.lp-table tbody tr:hover td {
  background-color: var(--lp-hover);
}

/* Row states. These replace `has-background-warning-light`,
   `has-background-success-light` and `has-background-danger-light`, which
   named a colour rather than what the row was, and which no two tables spelled
   the same way. */
.lp-table tbody tr.is-current td {
  background-color: var(--lp-current-bg);
  font-weight: 700;
}

.lp-table tbody tr.is-win td {
  background-color: var(--lp-win-bg);
}

.lp-table tbody tr.is-loss td {
  background-color: var(--lp-loss-bg);
}

.lp-table tbody tr.is-win:hover td {
  background-color: var(--lp-win-bg-hover);
}

.lp-table tbody tr.is-loss:hover td {
  background-color: var(--lp-loss-bg-hover);
}

.lp-table tbody tr.is-current:hover td {
  background-color: #fff6d9;
}

/* A column of figures reads as a column only if the digits line up: tabular
   numerals give every digit the same width, so 7 and 11 stack. Nothing but the
   match table did this, and every count on the club, team, progression and
   dashboard tables was ragged. */
.lp-table .lp-num {
  text-align: center;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.lp-table .lp-num-strong {
  font-weight: 700;
}

/* ===== TABLE SECTION HEADING =====

   One heading above every table. The site had four idioms — a dark primary
   box, an `h3.title is-3`, a coloured `h2.title is-5` and the page header —
   and two tables with no heading at all. */
.lp-table-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.15rem 0.75rem;
  margin-bottom: 0.6rem;
}

.lp-table-title {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--lp-text-muted);
}

.lp-table-meta {
  font-size: 0.75rem;
  color: var(--lp-text-muted);
}

/* A phone gets the same table, tighter, rather than a second copy of the
   markup. The wide tables — the rosters and the progression list — still hand
   over to a card list, because no amount of tightening fits eight columns. */
@media screen and (max-width: 768px) {
  .table.lp-table {
    font-size: 0.875rem;
  }

  .table.lp-table thead th,
  .table.lp-table tbody td {
    padding: 0.45rem 0.35rem;
  }
}

/* ===== CALENDAR TABLES =====

   The club page's next matches and the team page's calendar. Both were three
   columns of raw text: a "Jour" that restated the next column, an "Heure" that
   held the whole date, and a "Rencontre" of two names the reader had to search
   for his own team in. Two columns now — when, and who — and the row is read
   from that team's side. */

/* The time sits under the date rather than beside it: on a phone the second
   column needs every pixel it can get for a team name. */
.lp-cal-when {
  display: flex;
  flex-direction: column;
  line-height: 1.25;
}

.lp-cal-date {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Read at the same size as the date, and nearly as dark. The kick-off is half
   of what the reader came for — the federation's default is 19h00 and a
   derogation moves it — so it is not metadata about the date the way a
   division or a rank is metadata about a match. Set one step down and in the
   muted grey, it was the least legible thing in the row. */
.lp-cal-time {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--lp-text-soft);
  white-space: nowrap;
}

/* Wraps as a whole, so a long opponent goes to its own line under the pill
   instead of stretching the column past the width of the screen. */
.lp-cal-who {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.15rem 0.5rem;
  min-width: 0;
}

/* Both names break rather than hold: the club page carries two of them in one
   cell, and a club spells itself out ("ROYAL SPORTING CLUB BLEGNY-TREMBLEUR
   A"). Kept nowrap, either one is wider than a phone's whole column. */
.lp-cal-team {
  min-width: 0;
  font-weight: 700;
  overflow-wrap: anywhere;
}

.lp-cal-opponent {
  min-width: 0;
  color: var(--lp-text-soft);
  overflow-wrap: anywhere;
}

@media screen and (max-width: 768px) {
  /* The date column is `fixed-column`: it is as wide as its widest date and
     takes that width from the names beside it, which are the part that has to
     wrap. A step smaller here is a line fewer there. */
  .lp-cal-date,
  .lp-cal-time {
    font-size: 0.8125rem;
  }
}

/* ===== TABLE CARD LIST =====

   What a wide table becomes on a phone. Built on `.box`, which is what the
   club and team pages already used; the progression page used `.card` and was
   the odd one out. */
/* These sit inside the section's own box, so they flatten to a border rather
   than stacking a second shadow on the first — the same thing `.header-box`
   and `.lp-stat` do. `:not(:last-child)` matches the specificity of Bulma's
   own `.box` spacing rule, which would otherwise win and leave a 2.25rem gap. */
.lp-card-row {
  position: relative;
  display: block;
  padding: 0.85rem 1rem;
  box-shadow: none;
  border: 1px solid var(--lp-border-soft);
}

.lp-card-row:not(:last-child) {
  margin-bottom: 0.75rem;
}

.lp-card-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1.1rem;
  font-size: 0.75rem;
  color: var(--lp-text-muted);
}

.lp-card-stat-value {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--lp-text);
}

/* Player name and ranking alignment */
.player-name-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* ===== NAVBAR STYLES ===== */

/* Always visible navbar */
.navbar {
  position: sticky;
  top: 0;
  z-index: 30;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

/* Larger navbar logo and title */
.navbar-brand .navbar-item .icon-text {
  font-size: 1.5rem;
}

.navbar-brand .navbar-item .icon-text .icon {
  font-size: 1.5rem;
}

/* Hamburger styling - let Bulma handle the animation, just ensure visibility */
.navbar-burger span {
  background-color: #363636 !important;
}

/* Mobile & Tablet navbar layout - for 2 smallest screen sizes only */
@media screen and (max-width: 1023px) {
  .navbar-brand {
    display: flex !important;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    position: relative;
    padding: 0;
  }

  /* Burger icon - positioned at far left */
  .navbar-burger.is-hidden-desktop {
    order: 1;
    margin-left: 0;
    margin-right: 0;
    flex-shrink: 0;
    display: flex !important;
  }

  /* Logo/Title - centered */
  .navbar-brand .navbar-item {
    order: 2;
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    z-index: 1;
  }
}

/* Ensure body content doesn't overlap with sticky navbar */
body {
  padding-top: 0;
}

/* ===== PLAYER SEARCH STYLES ===== */

/* Search container */
.player-search-container {
  position: relative;
  width: 100%;
  max-width: 400px;
}

/* Search input */
.player-search-input {
  width: 100%;
  padding-left: 2.5em;
}

.player-search-input:focus {
  border-color: #3273dc;
  box-shadow: 0 0 0 0.125em rgba(50, 115, 220, 0.25);
}

/* Search icon - properly positioned inside input */
.player-search-container .control.has-icons-left .icon.is-left {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2.5em;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  z-index: 4;
}

.player-search-icon {
  color: var(--lp-text-muted);
  font-size: 1rem;
}

/* Clear button - positioned inside input */
.player-search-container .control.has-icons-right .icon.is-right {
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  width: 2.5em;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: all;
  cursor: pointer;
  z-index: 4;
}

.player-search-clear {
  color: var(--lp-text-muted);
  font-size: 1rem;
  transition: color 0.2s;
}

.player-search-clear:hover {
  color: #363636;
}

/* Search results dropdown */
.player-search-results {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 1000;
  margin-top: 0.25rem;
  background: white;
  border-radius: 6px;
  box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
  max-height: 400px;
  overflow-y: auto;
  display: none;
  border: 1px solid #dbdbdb;
  min-width: 100%;
  width: max-content;
  max-width: 90vw;
}

.player-search-results.is-active {
  display: block;
}

/* Result items */
.search-result-item {
  display: block;
  padding: 0.5rem 0.75rem;
  color: #4a4a4a;
  text-decoration: none;
  transition: background-color 0.2s;
  border-bottom: 1px solid #f5f5f5;
  text-align: left;
  white-space: nowrap;
  min-width: max-content;
}

.search-result-item:last-child {
  border-bottom: none;
}

.search-result-item:hover,
.search-result-item.is-active {
  background-color: #f5f5f5;
}

/* Result content */
.search-result-content {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  min-width: max-content;
}

.search-result-main {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.search-result-name {
  font-weight: 600;
  flex: 1;
  color: #363636;
}

.search-result-id {
  font-size: 0.75rem;
  font-weight: 400;
  color: var(--lp-text-muted);
}


.search-result-rank {
  font-size: 0.85rem;
  font-weight: 600;
}

/* Rank colour classes, on the site's palette rather than Bulma's tints:
   these carry white text, and the tints are too light to hold it. */
.search-result-rank.is-danger {
  background-color: var(--lp-loss);
  color: #fff;
}

.search-result-rank.is-warning {
  background-color: #ffdd57;
  color: rgba(0, 0, 0, 0.7);
}

.search-result-rank.is-success {
  background-color: var(--lp-win);
  color: #fff;
}

.search-result-rank.is-info {
  background-color: var(--lp-info);
  color: #fff;
}

.search-result-rank.is-light {
  background-color: #f5f5f5;
  color: #363636;
}

.search-result-club {
  font-size: 0.75rem;
  color: var(--lp-text-muted);
  margin-left: 0;
}

/* Mobile styles */
@media screen and (max-width: 768px) {
  .player-search-container {
    max-width: 100%;
  }

  .navbar-item .player-search-container {
    padding: 0.5rem;
  }

  .search-result-item {
    padding: 0.5rem 0.75rem;
  }

  .search-result-content {
    flex-wrap: wrap;
  }
}

/* Hide keyboard hint */
.search-keyboard-hint {
  display: none;
}

/* Mobile search centering when burger menu is active */
#mobile-search {
  text-align: center;
  padding: 2rem 1rem;
}

#mobile-search .section {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 1rem 0;
}

#mobile-search .player-search-container {
  max-width: 400px;
  width: 100%;
  margin: 0 auto;
}

/* Ensure mobile search results are left-aligned like desktop */
#mobile-search .player-search-results .search-result-item {
  text-align: left;
}

#mobile-search .player-search-results .search-result-content {
  text-align: left;
}

/* Club header styles */
.club-header-border {
  border-bottom: 1px solid #dbdbdb;
}

.club-header-actions {
  text-align: right;
}

.club-address-link {
  font-size: 0.9rem;
}

.club-itinerary-button {
  min-width: auto;
}


/* Modal styles */
.modal-card-head,
.modal-card-foot {
  padding: 0.75rem 1rem;
}

.modal-card-foot-spaced {
  justify-content: space-between;
}

.modal-card-body {
  max-height: calc(100vh - 200px);
  overflow-y: auto;
}
/* ===== PROGRESSION CHARTS ===== */

/* Rendered server-side as inline SVG: the player page ships no chart library.
   Both variants are in the HTML and the media query picks one — a viewBox wide
   enough for a desktop turns its labels into 5px smudges on a phone. */
.lp-chart-wide,
.lp-chart-tall {
  width: 100%;
  height: auto;
  display: block;
  font-family: inherit;
}

.lp-chart-tall {
  display: none;
}

@media screen and (max-width: 768px) {
  .lp-chart-wide {
    display: none;
  }

  .lp-chart-tall {
    display: block;
  }
}

/* ===== SEASON SWITCHER ===== */

/* The switcher always sits right under the page's own action button
   (Progressions, Tous les clubs, ...). Without a gap of its own the seasons
   read as more of those buttons, so it gets its own row, a hairline above it
   and pills rather than a single joined bar — nine seasons wrap on a phone,
   and a wrapped `has-addons` bar breaks apart mid-row. */
.season-switcher.buttons {
  gap: 0.4rem;
  margin-top: 1.75rem;
  margin-bottom: 0;
  padding-top: 1.25rem;
  border-top: 1px solid rgba(10, 10, 10, 0.1);
}

.season-switcher.buttons .button {
  margin: 0;
  border-radius: 9999px;
  min-width: 3.75rem;
}

.season-switcher.buttons .button.is-static {
  opacity: 0.6;
}

/* ===== PLAYER MATCH TABLE ===== */

/* One table per match day: a day is read as a block — the date, the club met
   and the division above it — and a table of its own keeps each day's rows
   from being separated by header rows inside a single long body. */
.lp-matches .lp-match-day + .lp-match-day {
  margin-top: 1.5rem;
}

.lp-match-day-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.15rem 0.75rem;
  padding-bottom: 0.4rem;
  margin-bottom: 0.35rem;
  border-bottom: 1px solid rgba(10, 10, 10, 0.1);
}

/* Who was met on the left, what the day was worth on the right. The two halves
   are grouped so that a narrow screen wraps them one under the other instead of
   stranding the day's total alone on a third line. */
.lp-match-day-title,
.lp-match-day-side {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  min-width: 0;
}

.lp-match-day-date {
  font-weight: 700;
  color: var(--lp-text);
  white-space: nowrap;
}

.lp-match-day-vs {
  color: var(--lp-text-soft);
  min-width: 0;
  overflow-wrap: anywhere;
}

.lp-match-day-meta {
  font-size: 0.75rem;
  color: var(--lp-text-muted);
  white-space: nowrap;
}

/* Where the match is played, from the reader's own side. The old tables said
   it only through the order of the two names — the page's player or team on
   the left meant he received — and reading a row from his own side would have
   lost it. Shared with the two calendar tables, which had no way of saying it
   at all. */
.lp-where {
  flex-shrink: 0;
  /* Inline-block so that the min-width below holds wherever the pill is put:
     `min-width` does nothing to a plain inline box, and today it only bites
     because every one of its three callers happens to be a flex container. */
  display: inline-block;
  /* Both labels take the width of the wider one. Left to their own widths,
     "DOMICILE" and "EXTÉRIEUR" differ by about ten pixels, and in a calendar
     column that is the difference between a row that fits on one line and the
     row above it that does not: two fixtures with equally long team names
     broke differently for no reason a reader could see. */
  min-width: 4.75rem;
  text-align: center;
  padding: 0.05rem 0.4rem;
  border-radius: 9999px;
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  white-space: nowrap;
}

.lp-where.is-home {
  background-color: #eef3fb;
  color: #3e6ba8;
}

.lp-where.is-away {
  background-color: #f5f5f5;
  color: var(--lp-text-muted);
}

/* The team match's own tally: the day's games added up, coloured like them. */
.lp-match-day-total {
  font-size: 0.875rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Fixed layout so that a long name wraps inside its own column instead of
   pushing the score and the points off the right edge of a phone. Rows are
   spaced rather than collapsed: a won row and a lost row that touch read as
   one striped block instead of two results. */
.table.lp-match-table {
  table-layout: fixed;
  width: 100%;
  margin-bottom: 0;
  background-color: transparent;
  border-collapse: separate;
  border-spacing: 0 3px;
}

.table.lp-match-table td {
  border: none;
  padding: 0.45rem 0.5rem;
}

.table.lp-match-table td:first-child {
  border-top-left-radius: var(--lp-radius-sm);
  border-bottom-left-radius: var(--lp-radius-sm);
}

.table.lp-match-table td:last-child {
  border-top-right-radius: var(--lp-radius-sm);
  border-bottom-right-radius: var(--lp-radius-sm);
}

.lp-match-won td {
  background-color: var(--lp-win-bg);
}

.lp-match-lost td {
  background-color: var(--lp-loss-bg);
}

.lp-match-won:hover td {
  background-color: var(--lp-win-bg-hover);
}

.lp-match-lost:hover td {
  background-color: var(--lp-loss-bg-hover);
}

/* The colour carries the result at a glance; the badge repeats it in a letter
   so the row still reads for someone who cannot tell the two tints apart. */
.lp-match-cell-result {
  width: 2.5rem;
}

.lp-match-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 9999px;
  font-size: 0.75rem;
  font-weight: 700;
  color: #fff;
}

.lp-match-won .lp-match-badge {
  background-color: var(--lp-win);
}

.lp-match-lost .lp-match-badge {
  background-color: var(--lp-loss);
}

.lp-match-opponent {
  font-weight: 600;
  overflow-wrap: anywhere;
}

.lp-match-rank {
  margin-left: 0.4rem;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--lp-text-muted);
  white-space: nowrap;
}

.lp-match-cell-score {
  width: 4.5rem;
  text-align: center;
}

.lp-match-score {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  color: var(--lp-text);
  white-space: nowrap;
}

.lp-match-score-sep {
  margin: 0 0.2rem;
  color: var(--lp-text-muted);
  font-weight: 400;
}

.lp-match-wo {
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--lp-text-muted);
}

.lp-match-cell-points {
  width: 3.5rem;
  text-align: right;
}

.lp-match-points {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  white-space: nowrap;
}

/* Points are already signed from the player's side, so the sign picks the
   colour: a win over a lower rank is worth nothing and stays grey. */
.lp-match-points.is-gain,
.lp-match-day-total.is-gain {
  color: var(--lp-win);
}

.lp-match-points.is-loss,
.lp-match-day-total.is-loss {
  color: var(--lp-loss);
}

.lp-match-points.is-flat,
.lp-match-day-total.is-flat {
  color: var(--lp-text-muted);
}

@media screen and (max-width: 768px) {
  .table.lp-match-table {
    font-size: 0.875rem;
  }

  .table.lp-match-table td {
    padding: 0.45rem 0.35rem;
  }

  .lp-match-cell-result {
    width: 2rem;
  }

  .lp-match-badge {
    width: 1.25rem;
    height: 1.25rem;
    font-size: 0.65rem;
  }

  .lp-match-cell-score {
    width: 3.75rem;
  }

  .lp-match-cell-points {
    width: 3rem;
  }

  .lp-match-day-side {
    width: 100%;
    justify-content: space-between;
  }
}

/* ===== PLAYER SEASON STATS ===== */

/* The season's figures were four sentences and a list; they are cards because
   each one is a single number a reader looks up, not a line he reads. The
   record leads on a row of its own — it is the only one with a shape to show —
   and the rest sit three abreast under it. */
.lp-stat-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.75rem;
}

.lp-stat-record {
  grid-column: 1 / -1;
}

@media screen and (min-width: 769px) {
  .lp-stat-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

.lp-stat {
  background-color: #fafafa;
  border: 1px solid #ededed;
  border-radius: 6px;
  padding: 0.7rem 0.85rem 0.75rem;
}

.lp-stat-label {
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--lp-text-muted);
}

.lp-stat-value {
  margin-top: 0.2rem;
  font-size: 1.75rem;
  font-weight: 700;
  line-height: 1.15;
  color: #363636;
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}

/* A classement is short and read as a word, not counted: it does not want the
   full numeral size, and it must not be spaced as digits. */
.lp-stat-value.is-rank {
  font-size: 1.5rem;
  font-variant-numeric: normal;
}

.lp-stat-value.is-gain {
  color: #257953;
}

.lp-stat-value.is-loss {
  color: #cc0f35;
}

.lp-stat-value.is-flat {
  color: var(--lp-text-muted);
}

.lp-stat-icon {
  margin-right: 0.45rem;
  font-size: 0.9rem;
  vertical-align: 0.15em;
  color: #b5b5b5;
}

.lp-stat-sub {
  margin-top: 0.15rem;
  font-size: 0.7rem;
  color: var(--lp-text-muted);
}

.lp-stat-record .lp-stat-value {
  font-size: 2rem;
}

.lp-stat-win {
  color: #257953;
}

.lp-stat-loss {
  color: #cc0f35;
}

/* The letters carry which number is which, so the two colours are never the
   only thing telling a win from a loss. */
.lp-stat-sep {
  margin: 0 0.7rem 0 0.15rem;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--lp-text-muted);
}

.lp-stat-sep:last-child {
  margin-right: 0;
}

/* The track is the season and the fill the part of it won: the same ratio the
   percentage states, in the one form that is read without arithmetic. */
.lp-stat-bar {
  display: flex;
  height: 6px;
  margin-top: 0.5rem;
  border-radius: 9999px;
  background-color: #fadbe1;
  overflow: hidden;
}

/* The fill has to be told apart from the track behind it, and #48c78e on the
   pink came to 1.66:1 — under the 3:1 a graphical indicator needs. */
.lp-stat-bar-win {
  display: block;
  height: 100%;
  border-radius: 9999px;
  background-color: var(--lp-win);
}

.lp-stat-teams {
  margin-top: 1rem;
  padding-top: 0.9rem;
  border-top: 1px solid rgba(10, 10, 10, 0.08);
}

/* One pill per team, so a player who turned out for four of them takes two
   lines rather than four. */
.lp-team-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.lp-team-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.15rem 0.25rem 0.15rem 0.7rem;
  border: 1px solid #e6e6e6;
  border-radius: 9999px;
  background-color: #fff;
  font-size: 0.8rem;
  font-weight: 600;
  color: #4a4a4a;
}

.lp-team-pill-count {
  min-width: 1.6rem;
  padding: 0 0.4rem;
  border-radius: 9999px;
  background-color: #eef3fb;
  color: #3e6ba8;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: center;
}

/* ===== DONATION PROGRESS BAR ===== */

/* The strip sits after </nav>, not inside it. The navbar is sticky, so a bar
   placed within it would hold viewport height on every screen for ever; outside,
   it is read once on load and then scrolls away with the page. */
.lp-donation-bar {
  display: none;
  flex-direction: column;
  gap: 0.35rem;
  text-decoration: none;
  color: inherit;
}

/* The JS unhides by clearing [hidden], so the shown state has to win over the
   display:none above without also overriding the attribute. */
.lp-donation-bar.is-full:not([hidden]) {
  display: flex;
}

.lp-donation-bar.is-full {
  padding: 0;
  gap: 0.5rem;
}

.lp-donation-track {
  position: relative;
  display: block;
  width: 100%;
  height: 6px;
  border-radius: 9999px;
  background-color: rgba(10, 10, 10, 0.12);
  overflow: hidden;
}

.lp-donation-bar.is-full .lp-donation-track {
  height: 14px;
}

.lp-donation-fill {
  display: block;
  height: 100%;
  border-radius: 9999px;
  background-color: #ffc107;
  /* At 6.7% the fill is a few pixels wide and reads as a rendering artefact
     rather than a value, so it is given a floor it cannot go under. */
  min-width: 3px;
}

/* The ticks are the campaign's checkpoints at their share of the goal. They are
   drawn over the fill, so a passed milestone still shows where it was. */
.lp-donation-tick {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  background-color: rgba(10, 10, 10, 0.25);
}

.lp-donation-labels {
  display: flex;
  width: 100%;
}

/* Each label owns the span of bar its checkpoint closes, so it sits under that
   segment rather than under the tick that ends it. */
.lp-donation-label {
  flex: 1 1 0;
  text-align: center;
  font-size: 0.7rem;
  color: var(--lp-text-muted);
}

.lp-donation-caption {
  font-size: 0.75rem;
  color: #4a4a4a;
  text-align: center;
  line-height: 1.3;
}

/* The donor count is the way to the donation page. It sits in a line of grey
   figures, so it is given the least affordance that still reads as clickable:
   the caption's own colour, underlined, and the site's link blue on hover. A
   blue word in the middle of that line would pull more attention than the
   donate button beside it. */
.lp-donation-donors {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.lp-donation-donors:hover {
  color: var(--lp-info);
}

@media screen and (max-width: 768px) {
  .lp-donation-bar.is-full .lp-donation-caption {
    font-size: 0.7rem;
  }
}

/* ===== THE HOMEPAGE DONATION APPEAL =====

   The Wikipedia-shaped banner: the site asking, above the fold on the one page
   every reader passes through. It is louder than the header strip on purpose —
   the strip is a control the reader may notice, this is a sentence he has to
   read past — and it is the only thing on the site allowed to be.

   Amber rather than red. Red is the site's loss colour, on every match row of
   every player page, and an ask painted in it reads as an error. The amber is
   already the donate button's, so the banner and its CTA are visibly one thing.

   Grid rather than flex: the prose and the progress bar stack in one column
   while the call to action sits beside them both, which no single flex line
   does. Under 768px it collapses to one column and the button goes full width —
   it is the reason the banner exists, and on a phone it is thumb-sized. */
.lp-appeal {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.5rem 2rem;
  align-items: center;
  max-width: 62rem;
  margin: 0 auto 1.5rem;
  padding: 1.25rem 1.5rem;
  /* The reader's own row colour on a standings table, which is what this is:
     the line the page wants him to look at. */
  background-color: var(--lp-current-bg);
  border: 1px solid var(--lp-current-border);
  /* Wikipedia's banner is a rule down the side rather than a box shouting at
     four edges. The left edge carries the weight; the rest only closes it. */
  border-left-width: 5px;
  border-radius: var(--lp-radius);
}

/* [hidden] has to win over the grid above, the way it does for the bars. */
.lp-appeal[hidden] {
  display: none;
}

.lp-appeal-eyebrow {
  grid-column: 1 / -1;
  grid-row: 1;
  margin: 0;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  /* The amber dark enough to read on white — see --lp-mid. The bright amber of
     the border is 1.75:1 and would make the label decorative. */
  color: var(--lp-mid);
}

.lp-appeal-text {
  grid-column: 1;
  grid-row: 2;
  color: var(--lp-text);
  line-height: 1.55;
}

.lp-appeal-text p {
  margin-bottom: 0.6rem;
}

.lp-appeal-text p:last-child {
  margin-bottom: 0;
}

.lp-appeal-progress {
  grid-column: 1;
  grid-row: 3;
  margin-top: 0.85rem;
}

.lp-appeal-cta {
  grid-column: 2;
  grid-row: 2 / 4;
  text-align: center;
}

.lp-appeal-button {
  font-weight: 600;
  /* Bulma's is-warning is the same amber as the banner's ground, so the button
     needs an edge of its own or it dissolves into it. */
  border: 1px solid #d99e00;
  box-shadow: 0 1px 2px rgba(10, 10, 10, 0.12);
}

@media screen and (max-width: 900px) {
  .lp-appeal {
    grid-template-columns: minmax(0, 1fr);
    padding: 1.1rem 1.1rem 1.25rem;
  }

  /* The column order is the desktop one read top to bottom, with one swap: the
     button comes before the progress bar rather than after it, so that what the
     banner is for is the last thing above the fold rather than the first thing
     below it. The bar is the evidence, and evidence can follow the ask. */
  .lp-appeal-text {
    grid-column: 1;
    grid-row: 2;
  }

  .lp-appeal-cta {
    grid-column: 1;
    grid-row: 3;
    margin-top: 1rem;
  }

  .lp-appeal-progress {
    grid-column: 1;
    grid-row: 4;
    margin-top: 1.25rem;
  }

  /* Full width, up to the point where a single button spanning the banner
     stops reading as a button. */
  .lp-appeal-button {
    display: flex;
    width: 100%;
    max-width: 24rem;
    margin: 0 auto;
  }
}

/* On a phone the banner has to keep its share of the screen, not its shape.

   Stacked, the same words run to eight lines instead of three, and the banner
   went from a third of a desktop viewport to half of a phone's: the reader saw
   the ask and then the top of one box, where a desktop reader saw the ask, the
   season and the first row of clubs. Nothing is dropped -- a phone reader gets
   the same text, the same bar and the same button -- it is set tighter, so that
   what is underneath keeps the same claim on the screen. */
@media screen and (max-width: 768px) {
  .lp-appeal {
    padding: 0.85rem 1rem 1rem;
    gap: 0.3rem 0;
  }

  .lp-appeal-text {
    font-size: 0.875rem;
    line-height: 1.45;
  }

  .lp-appeal-cta {
    margin-top: 0.8rem;
  }

  .lp-appeal-progress {
    margin-top: 0.9rem;
  }

  /* The bar's own furniture, at the size the rest of the banner now reads at. */
  .lp-appeal-progress .lp-donation-label,
  .lp-appeal-progress .lp-donation-caption {
    font-size: 0.68rem;
  }

  .lp-appeal-progress .lp-donation-track {
    height: 11px;
  }
}

/* The donation page's call to action, which now opens the page rather than
   closing it. Tinted like the homepage banner because it is the same ask, and
   because a reader who arrives here by mis-clicking the small link under that
   banner should recognise where he has landed before reading a word. */
.lp-donate-box {
  background-color: var(--lp-current-bg);
  border: 1px solid var(--lp-current-border);
}

.lp-donate-box p:last-child {
  margin-bottom: 0;
}
