/* Design tokens. Bulma 1.x derives its palette from these and follows
   prefers-color-scheme; [data-theme] forces a theme from the toggle. */
:root {
  --nomads-gap: 1rem;
  /* Tells the browser which theme the page is in, so its own widgets (scrollbars, form controls) are drawn to
     match. Without this a dark page still gets white scrollbars. Follows the OS unless the toggle forces one. */
  color-scheme: light dark;
}

:root[data-theme="light"] {
  color-scheme: light;
}

/* Touch targets and iOS no-zoom inputs */
.button,
.navbar-item,
.navbar-burger,
.tabs a {
  min-height: 44px;
}

.input,
.select select,
.textarea {
  font-size: 1rem;
  /* width: 100% must include the padding and border, or the control overflows its container */
  box-sizing: border-box;
  max-width: 100%;
}

/* An input joined to a button (search box, key box) matches the button's 44px touch height */
.field.has-addons .input {
  min-height: 44px;
}

/* Responsive table: wrapper scrolls horizontally, first column stays put */
.table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.table-scroll th:first-child,
.table-scroll td:first-child {
  position: sticky;
  left: 0;
  background: var(--bulma-scheme-main);
  z-index: 1;
}

/* Tables that start with a rank column (standings, head-to-head) keep both the rank and the
   name in view. The rank column has a fixed width so the name column knows where to stick. */
.table-scroll.sticky-2 {
  --rank-col: 2.5rem;
}

.table-scroll.sticky-2 th:first-child,
.table-scroll.sticky-2 td:first-child {
  width: var(--rank-col);
  min-width: var(--rank-col);
  max-width: var(--rank-col);
}

.table-scroll.sticky-2 th:nth-child(2),
.table-scroll.sticky-2 td:nth-child(2) {
  position: sticky;
  left: var(--rank-col);
  background: var(--bulma-scheme-main);
  z-index: 1;
  box-shadow: 1px 0 0 var(--bulma-border-weak); /* a hairline where the scrolling part slides under */
}

/* Frozen cells are opaque, so they must follow the zebra stripes themselves */
.table-scroll tbody tr:nth-child(even) > :first-child,
.table-scroll.sticky-2 tbody tr:nth-child(even) > :nth-child(2) {
  background: var(--bulma-table-striped-row-even-background-color);
}

/* Game cards: one per game, two rows (starter, replier); grid on wider screens */
.game-grid {
  display: grid;
  gap: 0.75rem;
  grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
}

.game {
  border: 1px solid var(--bulma-border-weak);
  border-radius: var(--bulma-radius);
  overflow: hidden;
}

/* Games still to play sit on a light grey, so they stand out from the finished ones */
.game.is-unplayed {
  background: var(--bulma-background);
}

.game-side {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.5rem 0.75rem;
  font-weight: 600; /* both players alike: the colour, not the weight, shows who won (a draw too) */
}

.game-side + .game-side {
  border-top: 1px solid var(--bulma-border-weak);
}

.game-side.is-winner {
  background: var(--tint-success-bg);
  color: var(--tint-success-fg);
}

.game-side.is-loser {
  background: var(--tint-danger-bg);
  color: var(--tint-danger-fg);
}

.game-side.is-draw {
  background: var(--tint-warning-bg);
  color: var(--tint-warning-fg);
}

.game-score {
  font-variant-numeric: tabular-nums;
}

/* Inline SVG bar chart (colours follow the Bulma theme, so dark mode just works) */
.bar-chart {
  display: block; /* an inline SVG leaves a few pixels of baseline space under itself */
  width: 100%;
  height: auto;
  max-width: 40rem;
}

.bar-chart .bar {
  fill: var(--bulma-link);
}

.bar-chart .grid {
  stroke: var(--bulma-border-weak);
}

.bar-chart .tick {
  fill: var(--bulma-text-weak);
  font-size: 11px;
}

/* Player picker chips: a styled checkbox, so it works without JS */
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.chip {
  position: relative;
  cursor: pointer;
}

.chip input {
  position: absolute;
  opacity: 0;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  cursor: pointer;
}

.chip span {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 1rem;
  border: 1px solid var(--bulma-border);
  border-radius: 999px;
  background: var(--bulma-scheme-main);
  user-select: none;
}

.chip input:checked + span {
  background: var(--bulma-link);
  border-color: var(--bulma-link);
  color: var(--bulma-link-invert);
  font-weight: 600;
}

.chip input:focus-visible + span {
  outline: 3px solid var(--bulma-link-text);
  outline-offset: 2px;
}

/* Score page, when one player is selected: their name is bold wherever it appears, in open and
   finished games. Everyone else drops to regular weight there (the green and red already show
   who won), so the bold name is the one thing that stands out. */
.score-cards.has-me .game-side {
  font-weight: 400;
}

.score-cards .game-name.is-me {
  font-weight: 700;
}

/* Admin fixture cards: a score form per game */
form.game {
  display: block;
}

.score-input {
  width: 5rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.game-side {
  align-items: center;
}

.game-header {
  padding: 0.25rem 0.75rem;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--bulma-text-weak);
  background: var(--bulma-scheme-main-bis);
  border-bottom: 1px solid var(--bulma-border-weak);
}

.game-footer .save-end {
  order: 2; /* after any repeat tag or message, pushed to the right edge */
  margin-left: auto;
}

.game-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.75rem;
  border-top: 1px solid var(--bulma-border-weak);
}


/* Bingos: chips under a game, and the small form to add one (disabled until the game has a score) */
.game-slot {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

/* The result box holds the chips under the result line; the entry form is a box of its own beside it on
   wider screens and below it, the same width, on narrow ones */
.game-chips .bingo-chips {
  margin-bottom: 0;
  padding: 0 0.75rem 0.5rem; /* here rather than on .game-chips, so a game without bingos adds no space */
}

/* Admin cards: the Save button sits right above the chips, so give them a little more room */
form.game .game-chips .bingo-chips {
  padding-top: 0.375rem;
}

.game-bingos {
  padding: 0;
}

/* Narrow screens: the whole game is one rounded box. The border moves from the result box (and the form's
   own box) to the slot around them, joined by a thin line between the result part and the bingo form */
@media (max-width: 599px) {
  .game-slot {
    gap: 0;
    border: 1px solid var(--bulma-border-weak);
    border-radius: var(--bulma-radius);
    overflow: hidden;
  }

  .game-slot > .game {
    border: 0;
    border-radius: 0;
  }

  .game-slot .bingo-form {
    border: 0;
    border-top: 1px solid var(--bulma-border-weak);
    border-radius: 0;
  }

  .game-bingos > .help {
    padding: 0 0.75rem 0.5rem;
  }
}

/* From tablet width up: one game per row, the game on the left and its bingos on the right */
@media (min-width: 600px) {
  .game-grid {
    grid-template-columns: 1fr;
  }

  .game-slot {
    display: grid;
    grid-template-columns: minmax(16rem, 1fr) minmax(0, 1fr);
    gap: 0.75rem;
    align-items: start;
  }

  /* Read-only results (no key, or an older night): one row per game across the whole container, as
     "Stewart  123 | 234  Greg", with the result line and the bingos in the same box underneath */
  .game-slot.is-view {
    display: block;
  }

  .game.is-readonly {
    display: grid;
    grid-template-columns: 1fr 1fr;
  }

  .game.is-readonly .game-side + .game-side {
    border-top: 0;
    border-left: 1px solid var(--bulma-border-weak);
    flex-direction: row-reverse; /* the second player's score comes first: 234  Greg */
  }

  .game.is-readonly .game-footer,
  .game.is-readonly .game-chips {
    grid-column: 1 / -1;
  }
}

.bingo-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin-bottom: 0.5rem;
}

.bingo-chip {
  height: auto;
  min-height: 1.75rem;
  padding: 0.125rem 0.5rem;
  gap: 0.3rem;
  font-size: 0.8125rem;
  white-space: normal;
}

.bingo-chip .bingo-word {
  letter-spacing: 0.04em;
}

.bingo-chip .bingo-score {
  opacity: 0.75;
  font-variant-numeric: tabular-nums;
}

.bingo-form {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0.75rem;
  border: 1px solid var(--bulma-border-weak);
  border-radius: var(--bulma-radius);
  background: var(--bulma-background); /* the same light grey as a game still to play */
}

.bingo-row {
  display: flex;
  gap: 0.5rem;
}

/* The player, word and score boxes and the Add button are all the same height (40px, not the usual 44px touch
   height), and line up along their tops */
.bingo-form .select,
.bingo-form .select select,
.bingo-form .input,
.bingo-form .button {
  box-sizing: border-box;
  height: 2.5rem;
  min-height: 2.5rem;
}

.bingo-row {
  align-items: flex-start;
}

.bingo-word-input {
  flex: 1 1 auto;
  min-width: 0;
  text-transform: uppercase;
}

.bingo-score-input {
  flex: 0 0 4.5rem;
  width: 4.5rem;
  text-align: right;
}

/* Entry page: "Add bingos" opens the form. A small triangle and plain text in the body colour (not link
   blue, which distracts), pointing right when closed and down when open; greyed out until the game has a score */
.bingo-toggle > summary,
p.bingo-toggle {
  padding: 0.5rem 0.75rem;
  color: var(--bulma-text);
  cursor: pointer;
  list-style: none;
}

.bingo-toggle > summary::-webkit-details-marker {
  display: none;
}

.bingo-toggle > summary::before,
p.bingo-toggle::before {
  content: "\25B6"; /* right-pointing triangle */
  display: inline-block;
  margin-right: 0.4rem;
  font-size: 0.7em;
  vertical-align: 0.1em;
}

details.bingo-toggle[open] > summary {
  padding-bottom: 0.25rem;
}

details.bingo-toggle[open] > summary::before {
  content: "\25BC"; /* down-pointing triangle */
}

p.bingo-toggle.is-disabled {
  color: var(--bulma-text-weak);
  opacity: 0.55;
  cursor: not-allowed;
  padding-bottom: 0.25rem;
}

/* Entry page, wide screens: each game is one box across the whole container. The row reads
   "Greg ........ 123 | 234 ........ Jason" (score inputs, on grey, before the scores are in), with the result
   line and bingos underneath and the "Add bingos" line attached below, inside the same rounded border.
   Scoped to .score-cards so the admin match night keeps its own layout. */
.score-cards .game-slot {
  display: block;
  border: 1px solid var(--bulma-border-weak);
  border-radius: var(--bulma-radius);
  overflow: hidden;
}

.score-cards .game-slot > .game {
  border: 0;
  border-radius: 0;
}

.score-cards .game-bingos {
  border-top: 1px solid var(--bulma-border-weak);
}

.score-cards .game-slot .bingo-form {
  border: 0;
  border-radius: 0;
}

.score-cards .game-bingos > .help {
  padding: 0 0.75rem 0.5rem;
}

@media (min-width: 600px) {
  .score-cards .game {
    display: grid;
    grid-template-columns: 1fr 1fr;
  }

  .score-cards .game .game-side + .game-side {
    border-top: 0;
    border-left: 1px solid var(--bulma-border-weak);
    flex-direction: row-reverse; /* the second player's score comes first: 234 ........ Jason */
  }

  .score-cards .game .game-side + .game-side .score-input {
    text-align: left; /* next to the divider, like the first score is */
  }

  .score-cards .game .game-footer,
  .score-cards .game .game-chips {
    grid-column: 1 / -1;
  }

  /* The open bingo form is one row: player, word, score, Add */
  .score-cards .bingo-form {
    flex-direction: row;
    align-items: flex-start;
  }

  .score-cards .bingo-player {
    flex: 0 0 12rem;
    width: 12rem;
  }

  .score-cards .bingo-form .bingo-row {
    flex: 1 1 auto;
    min-width: 0;
  }
}


/* Bingos on the night: a word cloud, bigger for a higher score, outlined if first ever played tonight */
.bingo-cloud {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.25rem 0.9rem;
  line-height: 1.25;
}

.cloud-word {
  font-weight: 600;
  letter-spacing: 0.03em;
  text-decoration: none;
}

.cloud-word.is-new {
  padding: 0 0.35em;
  border: 1.5px solid currentColor;
  border-radius: 0.5em;
}

.cloud-key {
  font-size: 0.75rem;
  font-weight: 400;
}

.bingo-length strong {
  font-variant-numeric: tabular-nums;
}


/* Light/dark toggle in the navbar: a sun or a moon in the navbar's own text and hover colours (it is an
   a.navbar-item, so Bulma styles it like the links). It shows the one you would switch to: the moon in light
   mode, the sun in dark. The rules are written twice, for an explicit choice and for the device setting. */
.theme-toggle {
  min-width: 2.75rem;
  justify-content: center;
  font-size: 1.35rem;
  line-height: 1;
}

.navbar-brand .theme-toggle {
  margin-left: auto; /* with the burger on its right, both pinned to the end of the bar */
}

.navbar-brand .theme-toggle ~ .navbar-burger {
  margin-left: 0;
}

.theme-toggle .theme-sun {
  display: none;
}

:root[data-theme="dark"] .theme-toggle .theme-sun {
  display: inline;
}

:root[data-theme="dark"] .theme-toggle .theme-moon {
  display: none;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle .theme-sun {
    display: inline;
  }

  :root:not([data-theme="light"]) .theme-toggle .theme-moon {
    display: none;
  }
}

/* While the theme changes, let the main surfaces fade rather than snap */
.theme-changing body,
.theme-changing .navbar,
.theme-changing .box,
.theme-changing .table,
.theme-changing .game,
.theme-changing .notification,
.theme-changing .footer,
.theme-changing input,
.theme-changing select,
.theme-changing .button {
  transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
}

@media (prefers-reduced-motion: reduce) {
  .theme-changing body,
  .theme-changing .navbar,
  .theme-changing .box,
  .theme-changing .table,
  .theme-changing .game,
  .theme-changing .notification,
  .theme-changing .footer,
  .theme-changing input,
  .theme-changing select,
  .theme-changing .button {
    transition: none;
  }
}

/* Page content is at most an iPad mini wide (768px) and stays centred on wider screens. The navbar is a
   little wider than that (by the section's side padding each side) and fills the screen on narrow ones. */
:root {
  --page-pad: 1.5rem; /* Bulma's .section side padding */
}

@media (min-width: 1024px) {
  :root {
    --page-pad: 3rem;
  }
}

.navbar > .container {
  max-width: calc(768px + 2 * var(--page-pad)) !important;
}

/* Bulma pulls the brand and menu out by an item's padding to line their text up with the page; here the
   bar is deliberately wider than the text, so the items keep their own padding */
.navbar > .container .navbar-brand {
  margin-inline-start: 0;
}

.navbar > .container .navbar-menu {
  margin-inline-end: 0;
}

main > .container {
  max-width: 768px !important; /* beats Bulma's breakpoint max-widths */
  margin-inline: auto;
}

/* Pairings preview: one "A v B" line per game, the first name starts */
.preview-games {
  list-style: none;
  margin: 0;
}

/* Section headings (Bulma's .subtitle) are bold everywhere */
.subtitle {
  --bulma-subtitle-weight: var(--bulma-weight-bold); /* Bulma sets this on .subtitle itself, so :root would lose */
}

/* A section heading that follows a table: the same 36px above it that "Standings for" gets under the filter row */
.heading-after-table {
  margin-top: 2.25rem;
}

/* Tinted surfaces: the result bands, bingo chips, and Bulma's "light" notifications and tags. Bulma keeps its
   pale 90%-lightness tints in dark mode, which glare and (with light text) fail contrast, so every tint
   is a pair of variables: Bulma's own light pair by default, deep tints with light text in dark mode. */
:root {
  --tint-success-bg: var(--bulma-success-light);
  --tint-success-fg: var(--bulma-success-light-invert);
  --tint-danger-bg: var(--bulma-danger-light);
  --tint-danger-fg: var(--bulma-danger-light-invert);
  --tint-warning-bg: var(--bulma-warning-light);
  --tint-warning-fg: var(--bulma-warning-light-invert);
  --tint-link-bg: var(--bulma-link-light);
  --tint-link-fg: var(--bulma-link-light-invert);
  --tint-info-bg: var(--bulma-info-light);
  --tint-info-fg: var(--bulma-info-light-invert);
  --tint-neutral-bg: var(--bulma-light);
  --tint-neutral-fg: var(--bulma-light-invert);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bulma-scheme-s: 30%; /* Bulma's dark greys are 14% saturated; a bluer, still dark, background */
    --tint-success-bg: hsl(153, 38%, 16%);
    --tint-success-fg: hsl(153, 45%, 82%);
    --tint-danger-bg: hsl(348, 38%, 19%);
    --tint-danger-fg: hsl(348, 85%, 88%);
    --tint-warning-bg: hsl(44, 45%, 17%);
    --tint-warning-fg: hsl(44, 85%, 82%);
    --tint-link-bg: hsl(233, 38%, 21%);
    --tint-link-fg: hsl(233, 100%, 88%);
    --tint-info-bg: hsl(198, 40%, 17%);
    --tint-info-fg: hsl(198, 80%, 85%);
    --tint-neutral-bg: hsl(220, 14%, 22%);
    --tint-neutral-fg: hsl(220, 15%, 82%);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark; /* so the browser's scrollbars and controls are dark too */
  --bulma-scheme-s: 30%;
  --tint-success-bg: hsl(153, 38%, 16%);
  --tint-success-fg: hsl(153, 45%, 82%);
  --tint-danger-bg: hsl(348, 38%, 19%);
  --tint-danger-fg: hsl(348, 85%, 88%);
  --tint-warning-bg: hsl(44, 45%, 17%);
  --tint-warning-fg: hsl(44, 85%, 82%);
  --tint-link-bg: hsl(233, 38%, 21%);
  --tint-link-fg: hsl(233, 100%, 88%);
  --tint-info-bg: hsl(198, 40%, 17%);
  --tint-info-fg: hsl(198, 80%, 85%);
  --tint-neutral-bg: hsl(220, 14%, 22%);
  --tint-neutral-fg: hsl(220, 15%, 82%);
}

.notification.is-success.is-light,
.tag.is-success.is-light {
  background-color: var(--tint-success-bg);
  color: var(--tint-success-fg);
}

.notification.is-danger.is-light,
.tag.is-danger.is-light {
  background-color: var(--tint-danger-bg);
  color: var(--tint-danger-fg);
}

.notification.is-warning.is-light,
.tag.is-warning.is-light {
  background-color: var(--tint-warning-bg);
  color: var(--tint-warning-fg);
}

.notification.is-link.is-light,
.tag.is-link.is-light {
  background-color: var(--tint-link-bg);
  color: var(--tint-link-fg);
}

.notification.is-info.is-light,
.tag.is-info.is-light {
  background-color: var(--tint-info-bg);
  color: var(--tint-info-fg);
}

.tag.is-light:not(.is-link):not(.is-success):not(.is-danger):not(.is-warning):not(.is-info) {
  background-color: var(--tint-neutral-bg);
  color: var(--tint-neutral-fg);
}

.bingo-chip .bingo-word a {
  color: inherit; /* the chip's own tint colour, not the link colour (which fails on the dark tint) */
}

/* Coloured text on the page background: Bulma's "on scheme" shades are picked for contrast in each theme */
.has-text-success {
  color: var(--bulma-success-on-scheme) !important;
}

.has-text-danger {
  color: var(--bulma-danger-on-scheme) !important;
}

/* The "Stewart won by 151" line: the theme's muted grey text, in both light and dark mode */
.result-line {
  color: var(--bulma-text-weak);
}

/* The bingo Add button is secondary to the score's Save button, so it is not the bright link blue. Light mode: a
   grey a step darker than the light grey form box it sits in. Dark mode: the mirror image, a grey a step lighter
   than the dark form box. */
.button.bingo-add {
  background-color: hsl(220, 13%, 85%);
  border-color: hsl(220, 13%, 75%);
  color: hsl(221, 14%, 15%);
}

.button.bingo-add:hover {
  background-color: hsl(220, 13%, 79%);
  border-color: hsl(220, 13%, 69%);
  color: hsl(221, 14%, 10%);
}

:root[data-theme="dark"] .button.bingo-add {
  background-color: hsl(221, 20%, 22%);
  border-color: hsl(221, 20%, 30%);
  color: hsl(221, 25%, 92%);
}

:root[data-theme="dark"] .button.bingo-add:hover {
  background-color: hsl(221, 20%, 27%);
  border-color: hsl(221, 20%, 36%);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .button.bingo-add {
    background-color: hsl(221, 20%, 22%);
    border-color: hsl(221, 20%, 30%);
    color: hsl(221, 25%, 92%);
  }

  :root:not([data-theme="light"]) .button.bingo-add:hover {
    background-color: hsl(221, 20%, 27%);
    border-color: hsl(221, 20%, 36%);
  }
}

/* The Logout item is a one-button form (it must POST); make the button read as a plain navbar item */
form.navbar-item.navbar-login {
  padding: 0;
}

.navbar-login-button {
  align-self: stretch; /* the whole item is the button, not just its text */
  width: 100%;
  padding: 0.5rem 0.75rem; /* a navbar item's own padding */
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: start;
  cursor: pointer;
}

/* Desktop only (where Bulma shows the full navbar): the Login (or Logout) item is outlined, in the theme's strongest text colour
   (black in light mode; near-white in dark mode, where a black outline would vanish into the page) */
@media (min-width: 1024px) {
  .navbar-item.navbar-login {
    align-self: center;
    min-height: 2.25rem;
    margin-inline-start: 0.5rem;
    padding: 0 1rem;
    border: 1px solid var(--bulma-text-strong);
    border-radius: var(--bulma-radius);
  }

  .navbar-login-button {
    width: auto;
    padding: 0 1rem;
    text-align: center;
  }
}

/* A test or staging site's banner (SITE_BANNER), above the navbar, in the theme's warning tint */
.site-banner {
  padding: 0.25rem 1rem;
  background: var(--tint-warning-bg);
  color: var(--tint-warning-fg);
  font-size: 0.875rem;
  font-weight: 600;
  text-align: center;
}

/* The results key with its copy button beside it; the key can also be selected with one tap or click */
.key-line {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}

#scorer-key {
  user-select: all;
}

[data-copy][hidden] {
  display: none;
}

/* A submit button that reads as a text link (for a small action that still has to be a POST) */
.link-button {
  padding: 0;
  border: 0;
  background: none;
  color: var(--bulma-link-text);
  font: inherit;
  text-decoration: underline;
  cursor: pointer;
}

/* The yearly gain on the home page: in light mode a green-on-green chip (the same tint as a won game), which
   stands out better on white; in dark mode plain green text, which already does */
.year-gain {
  display: inline-block;
  padding: 0.1rem 0.75rem;
  border-radius: 999px;
  background: var(--tint-success-bg);
  color: var(--tint-success-fg);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .year-gain {
    padding: 0;
    background: none;
    color: inherit;
  }
}

:root[data-theme="dark"] .year-gain {
  padding: 0;
  background: none;
  color: inherit;
}
