:root {
  --bg: #f3ede1;
  --ink: #1b1a17;
  --muted: #6d675c;
  --card: #fbf8f2;
  --line: #d9d0bf;
  --accent: #d6402b;
  --win: #2f7d4f;
  --lose: #c0392b;
  --draw: #8a7f6b;
  --shadow: 0 1px 0 var(--line), 0 12px 30px -18px rgb(40 30 10 / 0.35);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #15140f;
    --ink: #f1ebdf;
    --muted: #a39b8b;
    --card: #1f1d17;
    --line: #36322a;
    --accent: #ff6a4d;
    --win: #5fc58a;
    --lose: #ff7a68;
    --draw: #b5aa94;
    --shadow: 0 1px 0 var(--line), 0 12px 30px -18px rgb(0 0 0 / 0.8);
  }
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--ink);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 15px;
  line-height: 1.5;
}
button { font: inherit; color: inherit; cursor: pointer; }
button:focus-visible, input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

#fx {
  position: fixed; inset: 0; z-index: -1;
  width: 100%; height: 100%;
  pointer-events: none;
  opacity: 0; transition: opacity 1.2s ease;
}
#fx.ready { opacity: 1; }

.shell { max-width: 640px; margin: 0 auto; padding: 40px 16px 32px; }

.masthead { margin-bottom: 28px; }
.eyebrow { margin: 0 0 6px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.18em; font-size: 12px; }
h1 {
  margin: 0;
  font-family: "Fraunces", Georgia, serif;
  font-weight: 800;
  font-size: clamp(36px, 9vw, 60px);
  line-height: 0.95;
  letter-spacing: -0.02em;
}
h1 span { color: var(--accent); font-style: italic; font-weight: 500; }

.panel {
  background: color-mix(in srgb, var(--card) 78%, transparent);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: 24px;
  box-shadow: var(--shadow);
}
[hidden] { display: none !important; }

#loading { display: flex; align-items: center; gap: 14px; color: var(--muted); }
.spinner {
  width: 18px; height: 18px; flex: none;
  border: 2px solid var(--line); border-top-color: var(--accent); border-radius: 50%;
  animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.stepper { display: flex; gap: 8px; }
.stepper button, .presets button {
  border: 1px solid var(--line); background: transparent; border-radius: 12px;
}
.stepper button { width: 52px; font-size: 22px; }
.stepper input {
  flex: 1; min-width: 0; text-align: center;
  font: 600 28px "JetBrains Mono", monospace; color: var(--ink);
  background: var(--bg); border: 1px solid var(--line); border-radius: 12px; padding: 10px;
}
.presets { display: flex; gap: 8px; }
.presets button { flex: 1; padding: 8px 0; color: var(--muted); }
.presets button:hover, .stepper button:hover { border-color: var(--ink); color: var(--ink); }
.primary {
  border: 0; border-radius: 12px; padding: 14px 18px;
  background: var(--ink); color: var(--bg); font-weight: 600; letter-spacing: 0.04em;
}
.primary:hover { background: var(--accent); color: #fff; }

.scoreboard { display: grid; grid-template-columns: 1fr auto 1fr; align-items: end; gap: 12px; }
.side { display: flex; flex-direction: column; }
.side:last-child { text-align: right; }
.who { color: var(--muted); font-size: 12px; text-transform: uppercase; letter-spacing: 0.14em; }
.num { font: 800 44px/1 "Fraunces", serif; }
.mid { display: flex; flex-direction: column; align-items: center; gap: 2px; color: var(--muted); font-size: 12px; }
.round { color: var(--ink); font-weight: 600; font-size: 13px; }

.arena {
  margin: 22px 0 6px; padding: 18px 0;
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  border-block: 1px dashed var(--line);
}
.hand { font-size: clamp(56px, 16vw, 88px); text-align: center; line-height: 1; transition: transform 0.2s; }
.hand.mirrored { transform: scaleX(-1); }
.vs { font-family: "Fraunces", serif; font-style: italic; color: var(--muted); font-size: 20px; }
.arena.shaking .hand { animation: shake 0.45s ease-in-out; }
.arena.shaking .hand.mirrored { animation-name: shake-mirrored; }
@keyframes shake { 0%,100% { transform: translateY(0); } 25%,75% { transform: translateY(-14px); } 50% { transform: translateY(4px); } }
@keyframes shake-mirrored { 0%,100% { transform: scaleX(-1) translateY(0); } 25%,75% { transform: scaleX(-1) translateY(-14px); } 50% { transform: scaleX(-1) translateY(4px); } }

.verdict { text-align: center; min-height: 3em; margin: 8px 0 18px; }
.verdict b { display: block; font: 800 22px "Fraunces", serif; }
.verdict.win b { color: var(--win); }
.verdict.lose b { color: var(--lose); }
.verdict.draw b { color: var(--draw); }

.moves { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.move {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 14px 6px; border: 1px solid var(--line); border-radius: 14px; background: var(--bg);
  transition: transform 0.12s, border-color 0.12s;
}
.move .glyph { font-size: 34px; line-height: 1.1; }
.move .name { font-size: 12px; text-transform: uppercase; letter-spacing: 0.12em; color: var(--muted); }
.move:hover:not(:disabled) { transform: translateY(-2px); border-color: var(--ink); }
.move:disabled { opacity: 0.45; cursor: default; }

.final { margin-top: 18px; display: grid; gap: 12px; text-align: center; }
.final p { margin: 0; font-family: "Fraunces", serif; font-size: 20px; }

.history { margin: 22px 0 0; padding: 0; list-style: none; display: grid; gap: 6px; font-size: 13px; }
.history li {
  display: grid; grid-template-columns: 2.5em 1fr auto; gap: 10px; align-items: center;
  padding: 8px 10px; border-radius: 10px; background: var(--bg);
}
.history .n { color: var(--muted); }
.history .tag { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.1em; }
.history .win .tag { color: var(--win); }
.history .lose .tag { color: var(--lose); }
.history .draw .tag { color: var(--draw); }

.foot { margin-top: 24px; text-align: center; color: var(--muted); font-size: 12px; }
.foot a { color: var(--ink); text-underline-offset: 3px; }
.foot a:hover { color: var(--accent); }

@media (prefers-reduced-motion: reduce) {
  .arena.shaking .hand { animation: none; }
}

/* --- modes, forms, lobby -------------------------------------------------- */
.lede { margin: 0 0 14px; font: 500 22px "Fraunces", serif; }
.modes { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.mode {
  display: grid; gap: 4px; justify-items: start; text-align: left;
  padding: 18px; border: 1px solid var(--line); border-radius: 14px; background: var(--bg);
  transition: transform 0.12s, border-color 0.12s;
}
.mode:hover { transform: translateY(-2px); border-color: var(--ink); }
.mode .glyph { font-size: 30px; }
.mode b { font: 800 18px "Fraunces", serif; }
.mode small { color: var(--muted); font-size: 12px; }

.stack { display: grid; gap: 14px; }
.stack > label { font: 500 22px "Fraunces", serif; }
.text {
  width: 100%; padding: 12px 14px; font: 600 16px "JetBrains Mono", monospace; color: var(--ink);
  background: var(--bg); border: 1px solid var(--line); border-radius: 12px;
}
.code-input { text-transform: uppercase; letter-spacing: 0.3em; text-align: center; font-size: 22px; }
.split { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
fieldset { margin: 0; padding: 14px; display: grid; gap: 10px; border: 1px dashed var(--line); border-radius: 14px; }
legend { padding: 0 6px; color: var(--muted); font-size: 12px; text-transform: uppercase; letter-spacing: 0.12em; }
.primary.ghost { background: transparent; color: var(--ink); border: 1px solid var(--ink); }
.primary.ghost:hover { background: var(--ink); color: var(--bg); }
.link { border: 0; background: none; color: var(--muted); padding: 4px 0; justify-self: start; text-decoration: underline; text-underline-offset: 3px; }
.link:hover { color: var(--ink); }
.error { margin: 0; min-height: 1.5em; color: var(--lose); }

#lobby { display: grid; gap: 14px; justify-items: center; text-align: center; }
#lobby .eyebrow { margin: 0; }
.room-code { margin: 0; font: 800 64px/1 "Fraunces", serif; letter-spacing: 0.12em; }
.players { list-style: none; margin: 0; padding: 0; display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; }
.players li { padding: 6px 12px; border: 1px solid var(--line); border-radius: 999px; background: var(--bg); }
.waiting { display: flex; align-items: center; gap: 10px; color: var(--muted); margin: 0; }
#lobby .link { justify-self: center; }

/* --- play: camera, countdown, badges ---------------------------------------- */
.quit { margin-bottom: 12px; }
.arena { position: relative; }
.slot { position: relative; display: grid; place-items: center; min-height: 120px; }
.slot .hand { position: relative; }
.badge {
  position: absolute; top: 4px; right: 8px; padding: 2px 8px; border-radius: 999px;
  background: var(--ink); color: var(--bg); font-size: 12px;
}
.countdown {
  position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none;
  font: 800 clamp(64px, 20vw, 120px)/1 "Fraunces", serif; color: var(--accent);
  text-shadow: 0 4px 30px color-mix(in srgb, var(--accent) 45%, transparent);
}
.countdown.pop { animation: pop 0.5s cubic-bezier(0.2, 1.6, 0.4, 1); }
@keyframes pop { from { transform: scale(1.8); opacity: 0; } to { transform: scale(1); opacity: 1; } }
.arena.pumping .hand { animation: shake 1s ease-in-out infinite; }
.arena.pumping .hand.mirrored { animation-name: shake-mirrored; }
.camera-status { margin: 4px 0 0; text-align: center; color: var(--muted); font-size: 12px; }

.final .link { justify-self: center; }
.toast {
  position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 10;
  max-width: calc(100% - 32px); margin: 0; padding: 10px 16px; border-radius: 12px;
  background: var(--ink); color: var(--bg); box-shadow: var(--shadow);
}

@media (max-width: 480px) {
  .modes, .split { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
  .arena.pumping .hand, .countdown.pop { animation: none; }
}
.spinner { display: inline-block; }

.hand.concealed, .hand.mirrored.concealed {
  transform: none; font: 800 clamp(56px, 16vw, 88px)/1 "Fraunces", serif; color: var(--muted);
}
.arena.pumping .hand.concealed { animation-name: shake; }
.arena.pumping .vs { opacity: 0; }

/* --- live camera: both slots become matching frames; yours shows the feed --- */
.slot video, .slot canvas { display: none; }
.arena.live { grid-template-columns: 1fr auto 1fr; }
.arena.live .slot {
  aspect-ratio: 4 / 3; overflow: hidden; border-radius: 14px;
  border: 1px solid var(--line); background: #000;
}
.arena.live .slot-right { background: var(--bg); }
.arena.live .slot video, .arena.live .slot canvas {
  display: block; position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; transform: scaleX(-1);
}
.arena.live #hand-left {
  position: absolute; left: 8px; bottom: 8px; padding: 2px 8px;
  font-size: 34px; line-height: 1.2; border-radius: 12px;
  background: color-mix(in srgb, var(--bg) 70%, transparent); animation: none;
}

/* --- the reveal: each slot freezes on that player's photo at zero ------------------ */
.slot .photo {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 1;
  animation: photo-in 0.35s ease-out;
}
.slot.has-photo { aspect-ratio: 4 / 3; overflow: hidden; border-radius: 14px; }
.slot.has-photo .hand {
  position: absolute; left: 8px; bottom: 8px; z-index: 2; padding: 2px 8px;
  font-size: 34px; line-height: 1.2; border-radius: 12px;
  background: color-mix(in srgb, var(--bg) 70%, transparent);
}
.slot.has-photo .hand.mirrored { left: auto; right: 8px; }
.slot.has-photo .badge { z-index: 2; }
@keyframes photo-in { from { opacity: 0; scale: 1.06; } }
.camera-status { font-size: 13px; color: var(--ink); }

/* --- 5-second live throw: the count sits in the middle column, the feed stays clear --- */
.countdown { position: static; grid-column: 2; grid-row: 1; font-size: clamp(44px, 13vw, 76px); }
.arena > .vs { grid-column: 2; grid-row: 1; }
.move.selected { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, var(--bg)); }
.move.selected .name { color: var(--ink); }

/* --- play layout: round history beside the game on wide screens ---------------- */
.side-title {
  margin: 22px 0 10px; color: var(--muted); font: 600 12px "JetBrains Mono", monospace;
  text-transform: uppercase; letter-spacing: 0.14em;
}
.history { margin: 0; }
.history:empty::before { content: "No rounds yet"; color: var(--muted); font-size: 13px; }

@media (min-width: 960px) {
  /* While playing on a wide screen the game fills the window: no scrolling, and the
     camera frames take whatever height is left (sized with container query units). */
  .shell:has(#play:not([hidden])) {
    max-width: none; height: 100dvh; padding: 14px 28px 10px;
    display: flex; flex-direction: column;
  }
  .shell:has(#play:not([hidden])) .masthead {
    margin-bottom: 12px; display: flex; align-items: baseline; gap: 20px;
  }
  .shell:has(#play:not([hidden])) h1 { order: 1; font-size: 32px; }
  .shell:has(#play:not([hidden])) .masthead-top { order: 2; margin-left: auto; gap: 24px; }
  .shell:has(#play:not([hidden])) .masthead-top > * { margin: 0; }
  .shell:has(#play:not([hidden])) .foot { margin-top: 8px; }

  #play:not([hidden]) {
    flex: 1; min-height: 0; padding: 18px 24px;
    display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 28px;
  }
  .play-main { display: flex; flex-direction: column; min-height: 0; }
  .play-main .quit { margin-bottom: 4px; align-self: flex-start; }
  .play-main .arena {
    flex: 1; min-height: 180px; margin: 12px 0 4px; padding: 12px 0;
    container-type: size; align-content: center;
  }
  .arena.live { grid-template-columns: auto auto auto; justify-content: center; column-gap: 20px; }
  /* Two 4:3 frames side by side: as tall as the arena allows, as wide as the column allows. */
  .arena.live .slot { height: min(100cqh, calc((100cqw - 120px) * 3 / 8)); }
  .play-main .verdict { margin: 4px 0 12px; }
  .play-main .move { padding: 10px 6px; }

  .play-side {
    border-left: 1px dashed var(--line); padding-left: 24px;
    display: flex; flex-direction: column; min-height: 0;
  }
  .play-side .side-title { margin-top: 0; }
  .play-side .history { overflow-y: auto; min-height: 0; }
  .final p { font-size: 18px; }
}

.final-actions { display: flex; align-items: center; justify-content: center; gap: 18px; }
.final-actions .primary { flex: 1; max-width: 360px; }
.history li { grid-template-columns: 2.5em 1fr auto; }
.history .hands { font-size: 18px; letter-spacing: 0.04em; }

/* --- round outcomes: each result moves differently ------------------------------ */
@keyframes hand-triumph {
  0% { scale: 1; }
  35% { scale: 1.45; translate: 0 -20px; rotate: -10deg; }
  60% { scale: 1.15; translate: 0 2px; rotate: 6deg; }
  100% { scale: 1.2; translate: 0 0; rotate: 0deg; }
}
@keyframes hand-defeat {
  to { scale: 0.75; translate: 0 16px; rotate: 20deg; opacity: 0.4; filter: grayscale(1); }
}
@keyframes clash-left { 35% { translate: 36px 0; scale: 1.1; } 60% { translate: -8px 0; } 100% { translate: 0 0; } }
@keyframes clash-right { 35% { translate: -36px 0; scale: 1.1; } 60% { translate: 8px 0; } 100% { translate: 0 0; } }
@keyframes arena-shake {
  10%, 90% { translate: -2px 0; } 20%, 80% { translate: 4px 0; }
  30%, 50%, 70% { translate: -9px 0; } 40%, 60% { translate: 9px 0; }
}
@keyframes headline-pop { 0% { scale: 0.6; } 60% { scale: 1.18; } 100% { scale: 1; } }
@keyframes headline-shake { 25% { translate: -6px 0; } 50% { translate: 6px 0; } 75% { translate: -3px 0; } }
@keyframes headline-fade { from { opacity: 0; letter-spacing: 0.2em; } }
@keyframes confetti {
  to { translate: var(--dx) var(--dy); rotate: var(--spin); opacity: 0; }
}

.arena.outcome-win #hand-left,
.arena.outcome-lose #hand-right { animation: hand-triumph 0.7s cubic-bezier(0.2, 1.4, 0.4, 1) forwards; }
.arena.outcome-win #hand-left { filter: drop-shadow(0 0 16px color-mix(in srgb, var(--win) 70%, transparent)); }
.arena.outcome-lose #hand-right { filter: drop-shadow(0 0 16px color-mix(in srgb, var(--lose) 70%, transparent)); }
.arena.outcome-win #hand-right,
.arena.outcome-lose #hand-left { animation: hand-defeat 0.6s ease-in 0.15s forwards; }
.arena.outcome-lose { animation: arena-shake 0.5s ease-in-out; }
.arena.outcome-draw #hand-left { animation: clash-left 0.55s ease-out; }
.arena.outcome-draw #hand-right { animation: clash-right 0.55s ease-out; }
.verdict.win b { animation: headline-pop 0.5s ease-out; }
.verdict.lose b { animation: headline-shake 0.4s ease-in-out; }
.verdict.draw b { animation: headline-fade 0.5s ease-out; }

.confetti { position: absolute; left: 25%; top: 50%; pointer-events: none; }
.confetti i {
  position: absolute; width: 8px; height: 12px; border-radius: 2px;
  animation: confetti 1.1s cubic-bezier(0.15, 0.7, 0.3, 1) forwards;
}

@media (prefers-reduced-motion: reduce) {
  .arena[class*="outcome-"], .arena[class*="outcome-"] .hand, .verdict b { animation: none !important; }
}

/* With the camera on, each frame reacts to the result. */
.arena.live .slot { transition: box-shadow 0.3s, filter 0.4s; }
.arena.live.outcome-win .slot-left {
  box-shadow: 0 0 0 3px var(--win), 0 0 40px color-mix(in srgb, var(--win) 55%, transparent);
}
.arena.live.outcome-lose .slot-right {
  box-shadow: 0 0 0 3px var(--lose), 0 0 40px color-mix(in srgb, var(--lose) 55%, transparent);
}
.arena.live.outcome-lose .slot-left,
.arena.live.outcome-win .slot-right { filter: grayscale(1) brightness(0.6); }
.arena.live.outcome-draw .slot { box-shadow: 0 0 0 3px var(--draw); }

/* --- header: live count of online players -------------------------------------- */
.masthead-top { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.online-count {
  margin: 0 0 6px; display: inline-flex; align-items: center; gap: 8px;
  color: var(--muted); font-size: 12px; letter-spacing: 0.06em;
}
.online-count::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--win);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--win) 60%, transparent);
  animation: online-pulse 2s ease-out infinite;
}
@keyframes online-pulse { to { box-shadow: 0 0 0 8px transparent; } }
@media (prefers-reduced-motion: reduce) { .online-count::before { animation: none; } }

/* --- homepage: open lobbies and live matches -------------------------------------- */
.lobbies { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin-top: 8px; }
.room-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.room-list li {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 12px; border-radius: 12px; background: var(--bg); border: 1px solid var(--line);
}
.room-list li div { display: grid; gap: 2px; min-width: 0; }
.room-list b { font: 600 14px "JetBrains Mono", monospace; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.room-list small { color: var(--muted); font-size: 12px; }
.room-list li.empty { color: var(--muted); font-size: 13px; background: transparent; border-style: dashed; }
.primary.small { padding: 6px 14px; font-size: 13px; flex: none; }
.check { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 13px; cursor: pointer; }
.check input { accent-color: var(--accent); width: 16px; height: 16px; }
@media (max-width: 480px) { .lobbies { grid-template-columns: 1fr; } }

.masthead-top { align-items: center; }
.sound-toggle {
  margin: 0 0 6px; padding: 2px 6px; border: 1px solid var(--line); border-radius: 8px;
  background: transparent; font-size: 14px; line-height: 1.2;
}
.sound-toggle:hover { border-color: var(--ink); }

/* --- end of match: the result card ----------------------------------------------- */
.final {
  --tone: var(--draw);
  margin-top: 12px; padding: 18px 20px 16px; border-radius: 16px;
  border: 1px solid color-mix(in srgb, var(--tone) 70%, transparent);
  background: color-mix(in srgb, var(--tone) 10%, var(--card));
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--tone) 25%, transparent),
    0 18px 50px -20px color-mix(in srgb, var(--tone) 60%, transparent);
  animation: final-in 0.55s cubic-bezier(0.2, 1.3, 0.4, 1);
}
.final.win { --tone: var(--win); }
.final.lose { --tone: var(--lose); }
.final p { margin: 0; }
.final .final-headline {
  font: 800 clamp(30px, 4.2vw, 48px)/1.05 "Fraunces", serif; color: var(--tone); letter-spacing: -0.01em;
}
.final .final-score { font: 800 clamp(26px, 3vw, 36px)/1.1 "Fraunces", serif; color: var(--ink); }
.final .final-detail { color: var(--muted); font-size: 13px; }
@keyframes final-in { from { opacity: 0; scale: 0.9; translate: 0 12px; } }
@media (prefers-reduced-motion: reduce) { .final { animation: none; } }
.online-count { margin-left: auto; }
/* Once the match is over the result card says it all; give its space back to the frames. */
.play-main:has(#final:not([hidden])) .verdict,
.play-main:has(#final:not([hidden])) .camera-status { display: none; }

h1 a { color: inherit; text-decoration: none; }
h1 a:hover span { text-decoration: underline; text-decoration-thickness: 3px; text-underline-offset: 6px; }
.matches-count { margin: 0 0 6px; color: var(--muted); font-size: 12px; letter-spacing: 0.06em; }
.matches-count::before { content: "· "; }
