:root {
  --bg: #fff;
  --fg: #5f6368;
  --heading: #202124;
}

* {
  box-sizing: border-box;
}

/* The browser's own [hidden] rule comes from the UA stylesheet, so any author
   rule that sets display beats it — .new-game and .check are both display:flex,
   which left the rematch controls on screen for everyone even though the code
   had correctly set hidden. Make the attribute mean what it says. */
[hidden] {
  display: none !important;
}

body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--fg);
  font: 16px/1.5 'Segoe UI', Tahoma, sans-serif;
  -webkit-font-smoothing: antialiased;
}

.wrapper {
  margin: 12vh auto 0;
  max-width: 600px;
  padding: 0 16px;
  text-align: left;
}

.title {
  color: var(--heading);
  font-size: 1.6em;
  font-weight: 500;
  margin: 0 0 8px;
}

.status {
  margin: 0 0 4px;
  min-height: 1.5em;
}

.score {
  margin: 8px 0 0;
  min-height: 1.5em;
  font-variant-numeric: tabular-nums;
}

.hint {
  color: #9aa0a6;
  font-size: 0.85em;
  margin-top: 4px;
}

kbd {
  background: #f1f3f4;
  border: 1px solid #dadce0;
  border-radius: 3px;
  font-family: inherit;
  font-size: 0.85em;
  padding: 1px 5px;
}

/* The game itself ------------------------------------------------------- */

.game {
  height: 150px;
  max-width: 600px;
  position: relative;
  width: 100%;
}

.runner-container {
  background: #fff;
  direction: ltr;
  height: 150px;
  left: 0;
  max-width: 600px;
  overflow: hidden;
  position: absolute;
  top: 0;
  width: 44px; /* Expands to full width during the intro animation. */
  transition: filter 1.5s cubic-bezier(0.65, 0.05, 0.36, 1);
  will-change: filter;
}

.runner-container:focus {
  outline: none;
}

.runner-canvas {
  height: 150px;
  left: 0;
  max-width: 600px;
  opacity: 1;
  overflow: hidden;
  position: absolute;
  top: 0;
  z-index: 10;
}

/* Night mode. */
.runner-container.inverted {
  filter: invert(1);
}

/* Full screen touch target on mobile. */
.controller {
  height: 100vh;
  left: 0;
  position: absolute;
  top: 0;
  width: 100vw;
  z-index: 9;
}

#offline-resources {
  display: none;
}

/* Screens ---------------------------------------------------------------- */

.section-title {
  color: var(--heading);
  font-size: 1.1em;
  font-weight: 500;
  margin: 24px 0 8px;
}

.field { display: block; margin-bottom: 8px; }
.field-label { color: #9aa0a6; display: block; font-size: .8em; }

input, select {
  border: 1px solid #dadce0;
  border-radius: 4px;
  font: inherit;
  padding: 6px 8px;
}
input { width: 220px; }

button.primary {
  background: var(--heading);
  border: 0;
  border-radius: 4px;
  color: #fff;
  cursor: pointer;
  font: inherit;
  padding: 7px 16px;
}
button.primary:disabled { opacity: .5; cursor: default; }

.link-button {
  background: none;
  border: 0;
  color: #9aa0a6;
  cursor: pointer;
  font: inherit;
  padding: 0;
  text-decoration: underline;
}

.status { color: #9aa0a6; font-size: .85em; min-height: 1.2em; }
.status.is-error { color: #c5221f; }

/* Lobby browser ---------------------------------------------------------- */

.lobby-list, .player-list, .track {
  list-style: none;
  margin: 0;
  padding: 0;
}

.lobby-item { display: flex; gap: 6px; margin-bottom: 6px; }

.lobby-join {
  background: #f8f9fa;
  border: 1px solid #dadce0;
  border-radius: 6px;
  cursor: pointer;
  display: flex;
  font: inherit;
  justify-content: space-between;
  padding: 10px 14px;
  text-align: left;
  width: 100%;
}
.lobby-join:hover { background: #f1f3f4; border-color: #9aa0a6; }
.lobby-join:disabled { cursor: default; opacity: .55; }
.lobby-join:disabled:hover { background: #f8f9fa; border-color: #dadce0; }

/* A full room is still worth opening — you just arrive as a spectator. */
.lobby-watch {
  background: #fff;
  border: 1px solid #dadce0;
  border-radius: 6px;
  color: #5f6368;
  cursor: pointer;
  flex: 0 0 auto;
  font: inherit;
  font-size: .85em;
  padding: 10px 14px;
}
.lobby-watch:hover { background: #f1f3f4; border-color: #9aa0a6; }

.lobby-title { color: var(--heading); font-weight: 500; }
.lobby-meta { color: #9aa0a6; font-size: .85em; }
.lobby-empty { color: #9aa0a6; font-size: .9em; padding: 8px 0; }

.new-game { display: flex; flex-wrap: wrap; gap: 8px; }

.lobby-code-line { font-size: .9em; }
.lobby-code-line code {
  background: #f1f3f4;
  border-radius: 3px;
  font-size: 1.2em;
  letter-spacing: .1em;
  padding: 2px 8px;
}
.lobby-link { color: #9aa0a6; font-size: .85em; word-break: break-all; }

.player-list li { padding: 3px 0; }
.player-list .is-offline, .track-row.is-offline { opacity: .4; }

/* Race HUD --------------------------------------------------------------- */

.race-hud {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 4px;
}
.race-name { color: var(--heading); font-weight: 500; }
.race-timer {
  color: var(--heading);
  font-size: 1.4em;
  font-variant-numeric: tabular-nums;
}

.game-frame { position: relative; }

.countdown {
  align-items: center;
  color: var(--heading);
  display: flex;
  font-size: 4em;
  font-weight: 300;
  inset: 0;
  justify-content: center;
  pointer-events: none;
  position: absolute;
  z-index: 20;
}
.countdown.is-go { font-size: 1.6em; }

/* Progress track --------------------------------------------------------- */

.track { display: flex; flex-direction: column; margin-top: 10px; }

.track-row {
  align-items: center;
  display: flex;
  gap: 8px;
  padding: 1px 0;
}

.track-name {
  color: #5f6368;
  flex: 0 0 90px;
  font-size: .85em;
  overflow: hidden;
  text-align: right;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.track-row.is-you .track-name { color: var(--heading); font-weight: 600; }

.track-lane {
  background-image: radial-gradient(circle, #dadce0 1px, transparent 1px);
  background-position: 0 center;
  background-repeat: repeat-x;
  background-size: 6px 100%;
  flex: 1 1 auto;
  height: 26px;
  min-width: 0;
  position: relative;
}

.track-marker {
  bottom: 1px;
  image-rendering: pixelated;
  position: absolute;
}

.track-score {
  color: #9aa0a6;
  flex: 0 0 46px;
  font-size: .8em;
  font-variant-numeric: tabular-nums;
}

/* A big field: tighten the rows so the canvas and the whole track still fit
   on one screen. */
.track.is-dense .track-row { padding: 0; }
.track.is-dense .track-lane { height: 22px; }
.track.is-dense .track-name { font-size: .8em; }
.track.is-dense .track-score { font-size: .75em; }

/* Results ---------------------------------------------------------------- */

/* The standings and the track are one thing here: the figures sit directly
   above the line that produced them, so the gap between two players reads as
   a distance rather than as a number you have to compare. */
.track-row.is-detailed {
  border-bottom: 1px solid #f1f3f4;
  display: block;
  padding: 9px 0 4px;
  /* Tied together so the lane below stays flush with the name above it. */
  --rank-width: 24px;
  --head-gap: 10px;
}

.track-head {
  align-items: baseline;
  display: flex;
  gap: var(--head-gap);
}
.track-rank { color: #9aa0a6; flex: 0 0 var(--rank-width); }
.track-stats {
  color: #9aa0a6;
  font-size: .85em;
  font-variant-numeric: tabular-nums;
}

.track-row.is-detailed .track-name {
  /* Everybody who raced gets full-strength text here. The muted grey the live
     track uses reads as "inactive", which is wrong for a finished result. */
  color: var(--heading);
  flex: 1 1 auto;
  font-size: 1em;
  text-align: left;
}
/* The row is display:block here, so the lane — a <span> — must be made a block
   itself or it stays inline, collapses to nothing, and every dino piles up at
   the left edge regardless of its position. */
.track-row.is-detailed .track-lane {
  display: block;
  height: 30px;
  /* Start the lane where the name starts, not under the rank number, so a
     dino sits directly below the player it belongs to. */
  margin-left: calc(var(--rank-width) + var(--head-gap));
}

/* The standings record the race, not who still has the tab open. Fading a
   finished result because someone closed their browser makes the board look
   broken; connection state belongs on the live track only. */
.track-row.is-detailed.is-offline { opacity: 1; }

.track-row.is-detailed.is-winner .track-name { font-weight: 600; }
/* You, on the scoreboard */
.track-row.is-detailed.is-you .track-name { font-weight: 700; }
.track-row.is-detailed.is-you .track-stats { color: #5f6368; }


/* Fireworks */
.fireworks {
  height: 220px;
  left: 0;
  pointer-events: none;
  position: absolute;
  width: 100%;
  z-index: 30;
}
#screen-results { position: relative; }

.check {
  align-items: flex-start;
  color: #5f6368;
  display: flex;
  font-size: .85em;
  gap: 6px;
  margin-top: 8px;
}
.check input { width: auto; }

.race-timer.is-overtime {
  color: #188038;
  font-size: 1.1em;
  font-weight: 600;
  letter-spacing: .05em;
}

/* Overtime: players who have already crashed out */
.track-row.is-out { opacity: .45; }
.track-row.is-out .track-marker { filter: grayscale(1); }

/* Spectators -------------------------------------------------------------- */

.watching { color: #9aa0a6; font-size: .85em; margin: 4px 0 0; }

/* With no canvas to watch, the track is the whole show — give it the room. */
#screen-game.is-watching .track { margin-top: 20px; }
#screen-game.is-watching .track-row { padding: 7px 0; }
#screen-game.is-watching .track-name { flex-basis: 110px; font-size: .95em; }
#screen-game.is-watching .track-score { flex-basis: 56px; font-size: .9em; }

/* A crash is the only event the track can show, so make it show. */
@keyframes track-crash {
  0% { background-color: rgba(217, 48, 37, .22); }
  100% { background-color: transparent; }
}
.track-row.just-crashed { animation: track-crash .6s ease-out; }
