:root {
  --light: #f2dcb3;
  --dark: #bd815a;
  --text: #f4ecdf;
  --muted: #b8ab97;
  /* Player colours. Everything a player does on screen is tinted with theirs:
     badge, avatar ring, turn chip, last move, selection. */
  --w: #ffc247;
  --b: #4fd8e0;
  --check: #e5493a;
  --round: ui-rounded, "SF Pro Rounded", "Arial Rounded MT Bold", "Nunito", system-ui, sans-serif;
}
* { box-sizing: border-box; }
html { color-scheme: dark; }
body {
  margin: 0;
  min-height: 100dvh;
  background:
    radial-gradient(900px 620px at 50% -8%, rgba(120, 90, 190, 0.45), transparent 70%),
    linear-gradient(180deg, #1d1934, #0d0b17);
  color: var(--text);
  font: 15px/1.45 system-ui, sans-serif;
  display: flex;
  justify-content: center;
}
main {
  display: flex;
  /* Must claim the full width: body is a flex container, so without this main
     shrinks to fit its content and #game's percentage width has nothing real to
     resolve against. */
  width: 100%;
  padding: 24px 12px;
  align-items: center;
  justify-content: center;
}

/* One object: the badges sit on the same frame the board is set into.

   Sizing is a single constraint. The board fills whatever width the frame ends
   up with, and the frame takes the smallest of: the space available, a desktop
   maximum, and the largest width whose resulting square plus badges still fits
   the viewport height.

   That last term has two regimes, because badge height is clamp(52px, 10cqw,
   84px) and cqw is the frame's content width (W - 28). Fixed vertical chrome is
   76px: page padding 48, two gaps 20, badge borders 8. Frame and #game padding
   cancel, since they add height and take the same off the board's square.
     badges at their 52px floor:  W + 76 + 104 <= 100dvh
     badges scaling at 10cqw:     W + 76 + 0.2(W - 28) <= 100dvh
   The 84px ceiling is only reached past the 820px cap, so it never binds.

   The 320px floor is for landscape phones: below that the board becomes a
   postage stamp, and letting the page scroll is the better failure. */
#game {
  display: flex;
  flex-direction: column;
  container-type: inline-size;
  gap: 10px;
  width: min(100%, 820px, max(320px, min(calc(100dvh - 180px), calc((100dvh - 71px) / 1.2))));
  padding: 14px;
  border-radius: 28px;
  background:
    radial-gradient(120% 70% at 50% 0%, rgba(255, 235, 200, 0.1), transparent 60%),
    linear-gradient(160deg, #825a37, #4e3521 55%, #33231a);
  background-color: #2f2015;
  box-shadow:
    inset 0 1px 0 rgba(255, 225, 190, 0.22),
    inset 0 -2px 0 rgba(0, 0, 0, 0.45),
    0 2px 4px rgba(0, 0, 0, 0.5),
    0 34px 80px -20px rgba(0, 0, 0, 0.85);
}
#plaque-w { --player: var(--w); }
#plaque-b { --player: var(--b); }

/* ---- player badges ---- */
.plaque {
  display: flex;
  align-items: center;
  gap: clamp(10px, 1.7cqw, 18px);
  padding: 5px clamp(14px, 2.2cqw, 22px) 5px 5px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.3);
  border: 2px solid rgba(255, 255, 255, 0.05);
  box-shadow: inset 0 1px 0 rgba(255, 235, 205, 0.08), 0 2px 6px rgba(0, 0, 0, 0.35);
  min-height: clamp(52px, 10cqw, 84px);
  transition: background 0.25s, box-shadow 0.25s, border-color 0.25s;
}
.plaque .name {
  font-family: var(--round);
  font-weight: 800;
  font-size: clamp(20px, 3.4cqw, 32px);
  letter-spacing: 0.01em;
  color: var(--muted);
  transition: color 0.25s;
}
.plaque .wins {
  color: var(--player);
  font-size: clamp(12px, 2cqw, 19px);
  letter-spacing: 0.08em;
  opacity: 0.85;
  white-space: nowrap;
}
/* The avatar doubles as the turn light, so there is no separate dot. The initial
   sits underneath and shows through whenever a photo is missing or fails. */
.plaque .avatar {
  position: relative;
  width: clamp(40px, 7.6cqw, 68px);
  height: clamp(40px, 7.6cqw, 68px);
  flex: none;
  border-radius: 50%;
  overflow: hidden;
  display: grid;
  place-items: center;
  background: #2a2438;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.1);
  transition: box-shadow 0.25s;
}
.plaque .initial {
  font-family: var(--round);
  font-weight: 800;
  font-size: clamp(18px, 3.2cqw, 30px);
  color: var(--muted);
}
.plaque .avatar img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1);
  opacity: 0.85;
  transition: filter 0.25s, opacity 0.25s;
}
.plaque.active .avatar img, .plaque.winner .avatar img { filter: none; opacity: 1; }

.plaque .turn {
  margin-left: clamp(12px, 1.8cqw, 18px);
  padding: clamp(5px, 0.8cqw, 8px) clamp(11px, 1.7cqw, 16px);
  border-radius: 999px;
  background: var(--player);
  color: #1b1408;
  font-family: var(--round);
  font-size: clamp(11px, 1.5cqw, 14px);
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
  box-shadow: 0 2px 0 rgba(0, 0, 0, 0.35);
  animation: bob 1.6s ease-in-out infinite;
}
@keyframes bob {
  50% { translate: 0 -2px; }
}

.plaque .turn.check { background: var(--check); color: #fff; }
/* Winner shares the lit look but nothing pulses or bobs: nobody is waiting. */
.plaque.winner .turn, .plaque.winner .avatar { animation: none; }
.plaque.active, .plaque.winner {
  background: color-mix(in srgb, var(--player) 20%, rgba(0, 0, 0, 0.25));
  border-color: color-mix(in srgb, var(--player) 70%, transparent);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.12),
    0 2px 6px rgba(0, 0, 0, 0.35),
    0 0 0 4px color-mix(in srgb, var(--player) 18%, transparent),
    0 0 36px color-mix(in srgb, var(--player) 40%, transparent);
}
.plaque.active .name, .plaque.winner .name { color: #fff; }
.plaque.active .initial, .plaque.winner .initial { color: var(--player); }
.plaque.active .avatar, .plaque.winner .avatar {
  box-shadow: 0 0 0 3px var(--player);
  animation: pulse 1.8s ease-in-out infinite;
}
@keyframes pulse {
  50% { box-shadow: 0 0 0 3px var(--player), 0 0 0 9px color-mix(in srgb, var(--player) 25%, transparent); }
}
.plaque .captured { display: flex; margin-left: auto; height: clamp(22px, 3.6cqw, 32px); }
.plaque .captured img {
  height: clamp(22px, 3.6cqw, 32px);
  width: clamp(22px, 3.6cqw, 32px);
  margin-left: -7px;
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.5));
}
.plaque .mat {
  color: var(--player);
  font-family: var(--round);
  font-weight: 800;
  font-size: clamp(13px, 1.9cqw, 18px);
  min-width: 24px;
  text-align: right;
}

/* ---- board and frame ---- */
#frame {
  position: relative;
  padding: 12px;
}
/* Whichever side is to move colours the selection marks. Set from app.js. */
#game[data-turn="w"] { --turn: var(--w); }
#game[data-turn="b"] { --turn: var(--b); }
#board {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  border-radius: 6px;
  overflow: hidden;
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.75),
    0 0 0 5px rgba(150, 105, 65, 0.5),
    0 0 0 6px rgba(0, 0, 0, 0.4),
    0 14px 26px -8px rgba(0, 0, 0, 0.6),
    inset 0 2px 10px rgba(0, 0, 0, 0.28);
}
#squares { position: absolute; inset: 0; display: grid; grid-template: repeat(8, 1fr) / repeat(8, 1fr); }
#board { touch-action: manipulation; user-select: none; -webkit-tap-highlight-color: transparent; }
.sq { position: relative; cursor: pointer; }
.sq.light { background: linear-gradient(160deg, #f6e2bc, #ecd5aa); }
.sq.dark { background: linear-gradient(160deg, #c48a5f, #b27a51); }
/* The last move glows in the colour of whoever made it. Light and dark squares
   need different strengths, otherwise the light ones barely register. */
.sq.last::before { content: ''; position: absolute; inset: 0; }
.sq.dark.last-w::before { background: color-mix(in srgb, var(--w) 62%, transparent); }
.sq.light.last-w::before { background: color-mix(in srgb, #f0a300 52%, transparent); }
.sq.dark.last-b::before { background: color-mix(in srgb, var(--b) 62%, transparent); }
.sq.light.last-b::before { background: color-mix(in srgb, #12a9b3 50%, transparent); }
.sq.selected::before {
  content: '';
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--turn) 35%, transparent);
  box-shadow: inset 0 0 0 4px var(--turn);
}
.sq.check::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(circle, color-mix(in srgb, var(--check) 78%, transparent) 15%, color-mix(in srgb, var(--check) 14%, transparent) 75%);
  animation: alarm 1.1s ease-in-out infinite;
}
.sq.mate::before {
  animation: none;
  background: radial-gradient(circle, color-mix(in srgb, var(--check) 88%, transparent) 20%, color-mix(in srgb, var(--check) 30%, transparent) 80%);
}
@keyframes alarm {
  50% { opacity: 0.5; }
}
.sq.target::after {
  content: '';
  position: absolute;
  inset: 35%;
  border-radius: 50%;
  background: color-mix(in srgb, var(--turn) 70%, transparent);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}
.sq.capture::after {
  content: '';
  position: absolute;
  inset: 4%;
  border-radius: 50%;
  border: 5px solid color-mix(in srgb, var(--turn) 80%, transparent);
}

#pieces { position: absolute; inset: 0; pointer-events: none; }
.piece {
  position: absolute;
  width: 12.5%;
  height: 12.5%;
  transition: transform var(--move-ms, 180ms) ease;
  will-change: transform;
}
.piece.moving { z-index: 2; }
.piece img {
  width: 100%;
  height: 100%;
  display: block;
  filter: drop-shadow(0 3px 3px rgba(0, 0, 0, 0.35));
  transform-origin: 62% 92%;
  transition: opacity 0.2s, scale 0.2s, rotate 0.7s cubic-bezier(0.3, 1.5, 0.5, 1);
}
.piece.fallen img { rotate: 78deg; }
.piece.spawn img { opacity: 0; scale: 0.5; }
.piece.gone img { opacity: 0; scale: 0.6; }

/* ---- result ---- */
/* Lands over the middle of the board once the game ends. Compact on purpose:
   the final position should stay visible around it. Nothing is clickable
   after the end, so it takes no pointer events either. */
button { font: inherit; }
#outcome {
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  z-index: 3;
  min-width: 46%;
  padding: clamp(12px, 2.4cqw, 22px) clamp(18px, 3.4cqw, 32px);
  border-radius: clamp(16px, 2.6cqw, 24px);
  background: rgba(14, 11, 24, 0.86);
  border: 3px solid var(--win, rgba(255, 255, 255, 0.28));
  box-shadow:
    0 0 0 6px color-mix(in srgb, var(--win, #fff) 16%, transparent),
    0 24px 60px rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(6px);
  text-align: center;
  pointer-events: none;
  animation: land 0.45s cubic-bezier(0.2, 1.3, 0.4, 1) 0.4s backwards;
}
#outcome[hidden] { display: none; }
#outcome[data-winner="w"] { --win: var(--w); }
#outcome[data-winner="b"] { --win: var(--b); }
#outcome .headline {
  font: 800 clamp(26px, 6cqw, 52px)/1.05 var(--round);
  color: var(--win, var(--text));
}
#outcome .detail {
  margin-top: 0.35em;
  font: 700 clamp(12px, 2.1cqw, 17px)/1.2 var(--round);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}
#outcome .detail:empty { display: none; }
#outcome button {
  pointer-events: auto;
  display: block;
  margin: clamp(12px, 2cqw, 18px) auto 0;
  padding: clamp(9px, 1.4cqw, 13px) clamp(18px, 3cqw, 28px);
  border: 0;
  border-radius: 999px;
  background: var(--win, var(--text));
  color: #1b1408;
  font: 800 clamp(13px, 2cqw, 16px)/1 var(--round);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  box-shadow: 0 3px 0 rgba(0, 0, 0, 0.45);
  transition: translate 0.1s, box-shadow 0.1s, filter 0.1s;
}
#outcome button:hover { filter: brightness(1.08); translate: 0 -1px; box-shadow: 0 4px 0 rgba(0, 0, 0, 0.45); }
#outcome button:active { translate: 0 2px; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.45); }
#outcome button:disabled { opacity: 0.6; cursor: default; }
#outcome button[hidden] { display: none; }
@keyframes land {
  from { opacity: 0; scale: 0.8; }
}

/* ---- promotion ---- */
#promo {
  position: fixed;
  inset: 0;
  background: rgba(8, 6, 16, 0.7);
  display: flex;
  align-items: center;
  justify-content: center;
}
#promo[hidden] { display: none; }
.sheet {
  display: flex;
  gap: 10px;
  padding: 18px;
  border-radius: 22px;
  background: #241f36;
  border: 2px solid rgba(255, 255, 255, 0.08);
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.6);
}
.sheet button {
  width: 72px;
  height: 72px;
  padding: 8px;
  background: var(--light);
  border: 0;
  border-radius: 16px;
  cursor: pointer;
  transition: scale 0.12s;
}
.sheet button:hover { scale: 1.07; }
.sheet button img { width: 100%; height: 100%; }

@media (prefers-reduced-motion: reduce) {
  .plaque .turn, .plaque.active .avatar, .sq.check::before, #outcome { animation: none; }
}
