/* NixCon 2026 in pixels, like 2026.nixcon.org: sky blue with clouds, a dark
   bar on top, Press Start 2P for the game's labels and numbers, boxes with
   black pixel borders and notched corners, gold for the right answer and red
   for what went wrong. Questions and answers stay in a readable monospace. */

@font-face {
  font-family: "Plex Mono";
  font-weight: 400;
  font-display: swap;
  src: url(/vendor/ibm-plex-mono-latin-400-normal.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Plex Mono";
  font-weight: 600;
  font-display: swap;
  src: url(/vendor/ibm-plex-mono-latin-600-normal.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Plex Mono";
  font-weight: 400;
  font-display: swap;
  src: url(/vendor/ibm-plex-mono-latin-ext-400-normal.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
    U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Plex Mono";
  font-weight: 600;
  font-display: swap;
  src: url(/vendor/ibm-plex-mono-latin-ext-600-normal.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
    U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Press Start 2P";
  font-weight: 400;
  font-display: swap;
  src: url(/vendor/press-start-2p-latin-400-normal.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Press Start 2P";
  font-weight: 400;
  font-display: swap;
  src: url(/vendor/press-start-2p-latin-ext-400-normal.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
    U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --sky: #b5e2f7;
  --sheet: #f4fbfe;
  --ink: #2f2f2f;
  --ink-soft: #4b5a66;
  --rule: rgb(47 47 47 / 0.22);
  --accent: #5e6cc7;
  --heading: #065d9e;
  --gold: #ffd447;
  --panel: #38667f;
  --panel-light: #64879b;
  --red: #e70000;
  /* One pixel of the pixel art: borders, and the corners cut off boxes. */
  --px: 3px;
  --notch: polygon(
    var(--px) 0,
    calc(100% - var(--px)) 0,
    calc(100% - var(--px)) var(--px),
    100% var(--px),
    100% calc(100% - var(--px)),
    calc(100% - var(--px)) calc(100% - var(--px)),
    calc(100% - var(--px)) 100%,
    var(--px) 100%,
    var(--px) calc(100% - var(--px)),
    0 calc(100% - var(--px)),
    0 var(--px),
    var(--px) var(--px)
  );
  --pixel-font: "Press Start 2P", "Plex Mono", monospace;
  font-family: "Plex Mono", ui-monospace, Menlo, Consolas, "DejaVu Sans Mono", monospace;
  /* Everything is sized in rem, so this scales the whole page: 16px on
     phones, growing with the smaller of width and height on big screens
     (about 25px on a 1920x1080 display) so a question always fits. */
  font-size: clamp(16px, min(1.5vw, 2.3vh), 30px);
  line-height: 1.45;
  color: var(--ink);
  background: var(--sky);
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
}

/* Two pixel clouds drifting at the edges of the sky, faded so text on top
   of them stays readable. Phones have no room to spare for them. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background:
    url(/vendor/nixcon-2026-cloud.png) left -4rem top 7rem / 18rem auto no-repeat,
    url(/vendor/nixcon-2026-cloud.png) right -5rem bottom 4rem / 22rem auto no-repeat;
  image-rendering: pixelated;
  opacity: 0.35;
  pointer-events: none;
}

@media (max-width: 40rem) {
  body::before {
    display: none;
  }
}

::selection {
  background: var(--ink);
  color: #fff;
}

/* The header spans the page like the conference site's; everything below
   stays in a column. */
.view {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  --gutter: max(1rem, (100% - 44rem) / 2);
}

header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.75rem var(--gutter);
  border-bottom: 4px solid #606fce;
  background: var(--ink);
  color: #fff;
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.logo {
  flex: none;
  width: auto;
  height: 2.4rem;
}

h1 {
  margin: 0;
  font-family: var(--pixel-font);
  font-size: 0.8rem;
  font-weight: 400;
  line-height: 1.4;
  text-transform: uppercase;
}

#me {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  font-size: 0.8rem;
  line-height: 1.3;
  text-align: right;
}

#name {
  font-weight: 600;
}

#standing {
  color: var(--sky);
  font-variant-numeric: tabular-nums;
}

/* The clock is a health bar that runs out, block by block. */
#timer {
  position: relative;
  height: 1rem;
  margin: 1rem var(--gutter) 0;
  border: var(--px) solid var(--ink);
  background: var(--sheet);
}

#bar {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 0;
  background: repeating-linear-gradient(90deg, var(--accent) 0 0.8rem, transparent 0.8rem 1rem);
  transition: width 0.2s linear;
}

#bar.hurry {
  background: repeating-linear-gradient(90deg, var(--red) 0 0.8rem, transparent 0.8rem 1rem);
}

main {
  flex: 1;
  padding: 1.5rem var(--gutter) 1rem;
}

.label {
  margin: 0;
  color: var(--heading);
  font-size: 0.78rem;
  overflow-wrap: anywhere;
}

.question {
  margin: 0.4rem 0 1.4rem;
  font-size: clamp(1.2rem, 4.6vw, 1.6rem);
  font-weight: 600;
  line-height: 1.3;
  text-wrap: balance;
}

/* One choice per row, on any screen; only the spectator screen lays them
   out 2x2. */
.choices {
  display: grid;
  gap: 0.7rem;
  /* Also the answer form's fieldset. */
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

/* A pixel button: black border with the corners cut off and a shaded
   ledge along the bottom. */
.choice {
  position: relative;
  display: flex;
  align-items: stretch;
  min-height: 3.4rem;
  border: var(--px) solid var(--ink);
  background: var(--sheet);
  box-shadow: inset 0 -0.3rem 0 rgb(47 47 47 / 0.14);
  clip-path: var(--notch);
  color: var(--ink);
  font-size: 1rem;
  overflow: hidden;
}

.letter {
  flex: none;
  display: grid;
  place-items: center;
  width: 2.6rem;
  border-right: var(--px) solid currentColor;
  font-family: var(--pixel-font);
  font-size: 0.85em;
  z-index: 1;
}

.text {
  flex: 1;
  align-self: center;
  padding: 0.65rem 0.85rem;
  z-index: 1;
}

label.choice {
  cursor: pointer;
}

/* The radio stays in the page for keyboards and screen readers; the label is
   what you see and tap. */
label.choice input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

label.choice:hover {
  background: #fff;
}

label.choice:active {
  translate: 0 2px;
  box-shadow: none;
}

/* Inside the box: the notched corners clip anything drawn outside it. */
label.choice:has(:focus-visible) {
  outline: 2px dashed currentColor;
  outline-offset: -0.45rem;
}

label.choice:has(:checked) {
  background: var(--accent);
  box-shadow: inset 0 -0.3rem 0 rgb(0 0 0 / 0.22);
  color: #fff;
}

.choices:has(:checked) label.choice:not(:has(:checked)) {
  color: var(--ink-soft);
}

.choices:disabled label.choice {
  cursor: default;
  translate: none;
}

.choices:disabled label.choice:not(:has(:checked)) {
  opacity: 0.45;
}

/* One status line; which sentence shows depends on the form's state. */
.status {
  margin: 1rem 0 0;
  color: var(--ink-soft);
  font-size: 0.82rem;
}

#answer .picked,
#answer .expired,
#answer:has(:checked) .unpicked,
#answer:has(:disabled) .unpicked,
#answer:has(:disabled) .picked,
.status:has(.notice:not(:empty)) > :not(.notice) {
  display: none;
}

#answer:has(:checked) .picked,
#answer:has(:disabled) .expired {
  display: inline;
}

#answer:has(:disabled):has(:checked) .expired::after {
  content: ", your answer is locked in";
}

.notice {
  color: var(--red);
}

.countdown {
  margin: 1rem 0 0;
  color: var(--ink-soft);
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
}

.countdown.big {
  margin-top: 0.25rem;
  color: var(--ink);
  font-family: var(--pixel-font);
  font-size: 2rem;
  line-height: 1;
  text-align: right;
}

/* Reveal. */
.result {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  margin: 0 0 1.1rem;
}

.headline {
  font-family: var(--pixel-font);
  font-size: 1.6rem;
  line-height: 1.2;
}

.log {
  color: var(--ink-soft);
  font-size: 0.78rem;
}

.result.good .headline {
  color: var(--heading);
}

.result.bad .headline {
  color: var(--red);
}

.result.bad .log {
  color: var(--red);
}

.result.none .headline {
  color: var(--ink-soft);
}

.revealed {
  color: var(--ink-soft);
}

.revealed.correct {
  color: var(--ink);
  background: var(--gold);
}

.revealed.wrong {
  color: var(--red);
  border-color: var(--red);
}

.revealed.wrong .text {
  text-decoration: line-through;
  text-decoration-thickness: 2px;
}

.count {
  align-self: center;
  padding: 0 0.85rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  z-index: 1;
}

/* How many players picked this choice, hatched behind the row. */
.share {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  appearance: none;
  border: 0;
  background: transparent;
}

.share::-webkit-progress-bar {
  background: transparent;
}

.share::-webkit-progress-value {
  background: repeating-linear-gradient(
    -45deg,
    rgb(94 108 199 / 0.22) 0 3px,
    transparent 3px 8px
  );
}

.share::-moz-progress-bar {
  background: repeating-linear-gradient(
    -45deg,
    rgb(94 108 199 / 0.22) 0 3px,
    transparent 3px 8px
  );
}

/* A slate panel, like the site's "In short" box. */
.explanation {
  margin: 1.25rem 0 0;
  padding: 0.85rem 1rem;
  border: var(--px) solid var(--ink);
  background: var(--panel);
  box-shadow: inset 0 var(--px) 0 var(--panel-light);
  clip-path: var(--notch);
  color: #fff;
  font-size: 0.92rem;
}

.explanation::before {
  content: "# ";
  color: var(--sky);
  font-weight: 600;
}

/* Leaderboard. */
.leaderboard {
  margin: 0;
  padding: 0;
  list-style: none;
  border: var(--px) solid var(--ink);
  clip-path: var(--notch);
}

.leaderboard li {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.55rem 0.5rem;
  border-bottom: 1px solid var(--rule);
  background: var(--sheet);
}

.leaderboard li:last-child {
  border-bottom: none;
}

.leaderboard li:first-child {
  font-size: 1.15rem;
  font-weight: 600;
}

.leaderboard li.me {
  background: var(--gold);
}

.rank {
  width: 3.2rem;
  color: var(--heading);
  font-family: var(--pixel-font);
  font-size: 0.75em;
}

.leaderboard li.me .rank {
  color: var(--ink);
}

/* Dot leaders between name and score, like a table of contents. */
.who {
  flex: 1;
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  min-width: 0;
}

.who::after {
  content: "";
  flex: 1;
  border-bottom: 2px dotted var(--ink-soft);
}

.points {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

footer {
  display: flex;
  justify-content: space-between;
  margin: 0 var(--gutter);
  padding: 0.6rem 0 0.9rem;
  border-top: 1px solid var(--rule);
  color: var(--ink-soft);
  font-size: 0.78rem;
}

#connection {
  position: fixed;
  right: 1rem;
  bottom: 0.9rem;
  margin: 0;
  color: var(--red);
  font-size: 0.78rem;
}

/* On phones and tablets the choices are what you tap and read at arm's
   length: taller rows and bigger type throughout. */
@media (pointer: coarse), (max-width: 40rem) {
  body:not(.spectate) .question {
    font-size: clamp(1.4rem, 6.2vw, 1.9rem);
  }

  body:not(.spectate) .choices {
    gap: 0.8rem;
  }

  body:not(.spectate) .choice {
    min-height: 4.6rem;
    font-size: 1.3rem;
  }

  body:not(.spectate) .letter {
    width: 3.3rem;
  }

  body:not(.spectate) .text {
    padding: 0.9rem 1rem;
  }

  body:not(.spectate) .status,
  body:not(.spectate) .countdown:not(.big) {
    font-size: 1rem;
  }

  body:not(.spectate) .explanation {
    font-size: 1.1rem;
  }
}

/* Spectator screen for the livestream: fills a 16:9 frame at any resolution,
   so everything is sized from the viewport. 1920x1080 gives 24px. */
html:has(body.spectate) {
  font-size: min(1.25vw, 2.2222vh);
  overflow: hidden;
}

/* The game fills the stage above a strip on how to join. */
.stage {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr) 9.5rem;
  grid-template-areas:
    "game"
    "join";
  height: 100vh;
}

/* With a break slide, the slide takes the stage with the join strip below
   it, and the game moves into a column along the right. */
.stage:has(#slide:not(:empty)) {
  grid-template-columns: minmax(0, 1fr) 30rem;
  grid-template-rows: auto minmax(0, 1fr);
  grid-template-areas:
    "slide game"
    "join game";
}

.spectate #game {
  grid-area: game;
  min-width: 0;
  min-height: 0;
}

/* A slide in a pixel frame. */
#slide {
  grid-area: slide;
  padding: 1.6rem 1.6rem 0;
}

#slide:empty {
  display: none;
}

#slide img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: contain;
  border: var(--px) solid var(--ink);
  background: #fff;
  clip-path: var(--notch);
  image-rendering: auto;
  animation: slide-in 0.6s ease-out;
}

@keyframes slide-in {
  from {
    opacity: 0;
  }
}

/* Under the slide the strip has room for a bigger code, with the steps
   below the address. */
.stage:has(#slide:not(:empty)) .join {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-content: center;
  column-gap: 2rem;
  row-gap: 1rem;
  margin: 1.6rem 1.6rem 0;
  padding: 1.2rem 1.6rem;
  border: var(--px) solid var(--ink);
  border-bottom: none;
}

.stage:has(#slide:not(:empty)) .qr {
  grid-row: span 2;
  height: 10rem;
}

.stage:has(#slide:not(:empty)) .steps {
  margin: 0;
  padding: 1rem 0 0;
  border-left: none;
  border-top: 1px solid rgb(255 255 255 / 0.25);
  font-size: 0.95rem;
  line-height: 1.55;
}

/* The game in the column: one choice per row and smaller type, sized so the
   longest questions and explanations still fit. */
.stage:has(#slide:not(:empty)) #game {
  border-left: var(--px) solid var(--ink);
  background: var(--sheet);
}

.stage:has(#slide:not(:empty)) header {
  padding: 1.1rem 1.4rem 0.9rem;
}

.stage:has(#slide:not(:empty)) h1 {
  font-size: 0.8rem;
}

.stage:has(#slide:not(:empty)) #tally {
  font-size: 0.95rem;
}

.stage:has(#slide:not(:empty)) #timer {
  height: 0.9rem;
  margin: 0.7rem 1.4rem 0;
}

.stage:has(#slide:not(:empty)) main {
  padding: 0.8rem 1.4rem 0.9rem;
}

.stage:has(#slide:not(:empty)) .label {
  font-size: 0.75rem;
}

.stage:has(#slide:not(:empty)) .question {
  margin: 0.3rem 0 0.9rem;
  font-size: 1.4rem;
  line-height: 1.3;
}

.stage:has(#slide:not(:empty)) .choices {
  grid-template-columns: 1fr;
  gap: 0.5rem;
}

.stage:has(#slide:not(:empty)) .choice {
  min-height: 2.8rem;
  font-size: 1.05rem;
}

.stage:has(#slide:not(:empty)) .text {
  padding: 0.5rem 0.75rem;
}

.stage:has(#slide:not(:empty)) .letter {
  width: 2.6rem;
}

.stage:has(#slide:not(:empty)) .countdown.big {
  font-size: 2.4rem;
}

.stage:has(#slide:not(:empty)) .explanation {
  margin-top: 0.9rem;
  padding: 0.6rem 0.8rem;
  font-size: 0.95rem;
}

.stage:has(#slide:not(:empty)) .leaderboard {
  grid-template-rows: none;
  grid-auto-flow: row;
}

.stage:has(#slide:not(:empty)) .leaderboard li {
  padding: 0.35rem 0.5rem;
  font-size: 1.1rem;
}

.stage:has(#slide:not(:empty)) .leaderboard li:first-child {
  font-size: 1.3rem;
}

.spectate .view {
  height: 100%;
  min-height: 0;
  max-width: none;
}

.spectate header {
  padding: 1.1rem 2rem 0.9rem;
}

.spectate .logo {
  height: 2.8rem;
}

.spectate h1 {
  font-size: 1rem;
}

#tally {
  font-size: 1.1rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.spectate #timer {
  height: 1.2rem;
  margin: 1.1rem 2rem 0;
}

.spectate main {
  display: flex;
  flex-direction: column;
  padding: 1.6rem 2rem 1.2rem;
  overflow: hidden;
}

.spectate .label {
  font-size: 0.9rem;
}

.spectate .question {
  margin: 0.4rem 0 1.4rem;
  font-size: 2.3rem;
}

.spectate .choices {
  grid-template-columns: 1fr 1fr;
  gap: 0.9rem;
}

.spectate .choice {
  min-height: 4.2rem;
  font-size: 1.35rem;
}

.spectate .letter {
  width: 3.4rem;
}

.spectate .countdown {
  margin-top: auto;
  font-size: 1.1rem;
}

.spectate .countdown.big {
  font-size: 3.4rem;
}

.spectate .explanation {
  margin-top: 1.2rem;
  font-size: 1.25rem;
}

/* Top ten in two columns of five, filled downwards, so it fits above the
   join strip. */
.spectate .leaderboard {
  display: grid;
  grid-template-rows: repeat(5, auto);
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  align-content: start;
  background: var(--sheet);
}

.spectate .leaderboard li:nth-child(n + 6) {
  border-left: 1px solid var(--rule);
}

.spectate .leaderboard li {
  padding: 0.45rem 0.6rem;
  font-size: 1.3rem;
}

.spectate .leaderboard li:first-child {
  font-size: 1.6rem;
}

/* The join strip along the bottom: code, address, and how to play, on a
   slate panel. */
.join {
  grid-area: join;
  display: flex;
  align-items: center;
  gap: 1.6rem;
  padding: 0.8rem 2rem;
  border-top: var(--px) solid var(--ink);
  background: var(--panel);
  box-shadow: inset 0 var(--px) 0 var(--panel-light);
  color: #fff;
}

.join p {
  margin: 0;
}

.join .how {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.join .label {
  color: var(--sky);
  font-family: var(--pixel-font);
  font-size: 0.7rem;
  text-transform: uppercase;
}

.join .url {
  font-family: var(--pixel-font);
  font-size: 1.5rem;
  line-height: 1.2;
}

.join .hint {
  color: #d3e7f1;
  font-size: 0.9rem;
}

.steps {
  margin: 0 0 0 auto;
  padding: 0 0 0 1.6rem;
  border-left: 1px solid rgb(255 255 255 / 0.25);
  list-style: none;
  counter-reset: step;
  font-size: 1rem;
  line-height: 1.7;
}

.steps li {
  counter-increment: step;
}

.steps li::before {
  content: counter(step) ". ";
  color: var(--gold);
  font-weight: 600;
}

.qr {
  flex: none;
  height: 100%;
  width: auto;
  aspect-ratio: 1;
  border: var(--px) solid var(--ink);
}

.qr rect {
  fill: #fff;
}

.qr path {
  fill: var(--ink);
}
