* {
  box-sizing: border-box;
  -webkit-tap-highlight-color: transparent;
}

:root {
  --bg: #12161c;
  --panel: #1a2029;
  --board: #222b36;
  --cell: rgba(255,255,255,.05);
  --ink: #e8eef4;
  --ink-dim: #8c9bab;
  --line: #2f3b49;
  --accent: #35c6a8;
  --accent-ink: #06231e;
  --good: #35c6a8;
  --bad: #e2555f;
}


html, body {
  margin: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  background: var(--bg);
  color: var(--ink);
}

body {
  display: flex;
  align-items: center;
  justify-content: center;
}

button,
input {
  font: inherit;
}

button {
  border: 0;
  cursor: pointer;
}

.hidden {
  display: none !important;
}

/* =========================================================
   LOBBY
========================================================= */

#lobby {
  width: min(520px, calc(100vw - 32px));
  text-align: center;
}

.logo {
  font-size: clamp(42px, 10vw, 72px);
  font-weight: 900;
  letter-spacing: -4px;
  color: var(--ink);
  margin-bottom: 4px;
}

.subtitle {
  color: var(--ink-dim);
  margin-bottom: 30px;
}

.card {
  background: var(--panel);
  border-radius: 18px;
  padding: 24px;
  box-shadow: 0 18px 50px rgba(0,0,0,.45);
}

.input {
  width: 100%;
  border: 2px solid var(--line);
  background: #131920;
  border-radius: 12px;
  padding: 14px 16px;
  outline: none;
  color: var(--ink);
  font-size: 18px;
  margin-bottom: 12px;
}

.input:focus {
  border-color: var(--accent);
}

.btn {
  width: 100%;
  border-radius: 12px;
  padding: 14px 18px;
  font-weight: 800;
  font-size: 16px;
  margin-top: 8px;
  background: var(--accent);
  color: var(--accent-ink);
}

.btn.secondary {
  background: var(--board);
}

.btn:active {
  transform: scale(.98);
}

.divider {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 22px 0;
  color: var(--ink-dim);
}

.divider::before,
.divider::after {
  content: "";
  height: 1px;
  background: var(--line);
  flex: 1;
}

.status {
  min-height: 24px;
  margin-top: 16px;
  font-weight: 700;
  color: var(--accent);
}

.room-code {
  font-size: 42px;
  font-weight: 900;
  letter-spacing: 8px;
  margin: 10px 0 16px;
  color: var(--ink);
}

/* =========================================================
   GAME
========================================================= */

#game {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.topbar {
  height: 72px;
  flex: 0 0 72px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 18px;
  gap: 12px;
}

.top-title {
  font-weight: 900;
  font-size: 22px;
}

.connection {
  font-size: 13px;
  font-weight: 800;
  color: var(--ink-dim);
}

.connection.online {
  color: var(--good);
}

.connection.offline {
  color: var(--bad);
}

.room-small {
  font-size: 12px;
  color: var(--ink-dim);
}

/* The tracks shrink-wrap the boards, so the grid gap really is the
   distance between them - which is what the bridge is measured
   against. Stretchy tracks would leave slack the bridge cannot see. */
.boards {
  position: relative;
  touch-action: none;
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: auto auto;
  justify-content: center;
  align-content: center;
  gap: clamp(44px, 8vw, 132px);
  padding: 0 clamp(8px, 3vw, 36px) 12px;
}

.player {
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.player-header {
  width: min(100%, 600px);
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 4px 4px 8px;
}

.player-name {
  font-weight: 900;
  font-size: clamp(15px, 2vw, 20px);
}

.score-box {
  display: flex;
  gap: 6px;
}

.score {
  min-width: 65px;
  background: var(--board);
  color: white;
  border-radius: 8px;
  text-align: center;
  padding: 5px 9px;
  font-size: 11px;
  text-transform: uppercase;
  font-weight: 800;
}

.score strong {
  display: block;
  font-size: 16px;
}

/* Board is square and limited by both width and height */
.board-wrap {
  position: relative;
  width: min(
    calc((100vh - 130px) * .92),
    calc((100vw - 90px) / 2.25),
    600px
  );
  aspect-ratio: 1;
}

.board {
  width: 100%;
  height: 100%;
  background: var(--board);
  border-radius: clamp(8px, 1.5vw, 14px);
  padding: 2.2%;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  grid-template-rows: repeat(5, 1fr);
  gap: 1.9%;
  box-shadow: 0 10px 26px rgba(0,0,0,.45);
}

.cell {
  background: var(--cell);
  border-radius: 7%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: clamp(15px, 3vw, 34px);
  font-weight: 900;
  user-select: none;
  position: relative;
  overflow: hidden;
}

.cell[data-value="2"] {
  background: #2b3a4a;
  color: #c7d8e8;
}

.cell[data-value="4"] {
  background: #31506b;
  color: #dbeaf6;
}

.cell[data-value="8"] {
  background: #2f7d8c;
  color: #eafaff;
}

.cell[data-value="16"] {
  background: #35a08a;
  color: #062420;
}

.cell[data-value="32"] {
  background: #57b85f;
  color: #06210c;
}

.cell[data-value="64"] {
  background: #9dc93f;
  color: #12220a;
}

.cell[data-value="128"] {
  background: #e0b73c;
  color: #221a04;
  font-size: clamp(13px, 2.4vw, 25px);
}

.cell[data-value="256"] {
  background: #ef9235;
  color: #241202;
  font-size: clamp(13px, 2.4vw, 25px);
}

.cell[data-value="512"] {
  background: #ef6b3d;
  color: #fff;
  font-size: clamp(13px, 2.4vw, 25px);
}

.cell[data-value="1024"] {
  background: #e14b6a;
  color: #fff;
  font-size: clamp(12px, 2.3vw, 23px);
}

.cell[data-value="2048"] {
  background: #b45cd6;
  color: #fff;
  font-size: clamp(12px, 2.3vw, 23px);
}

.cell[data-value="4096"] {
  background: #7a5cf0;
  color: #fff;
  font-size: clamp(12px, 2.3vw, 23px);
}

/* =========================================================
   CORRIDOR

   One cell of board, sitting in the gap between the two boards
   and lined up with the middle cell of each. JS sizes it from
   the live cell geometry, so it carries on the same grid in
   both layouts.
========================================================= */

.corridor {
  position: fixed;
  z-index: 5;
  pointer-events: none;
  background: var(--board);
  opacity: 0;
  transition: opacity .25s;
}

.corridor.show {
  opacity: 1;
}

/* The cell in the channel. Same size, gap and corners as one on
   a board, because it is measured from one. */
.corridor-cell {
  position: absolute;
  inset: var(--corridor-gap, 6px);
  border-radius: 7%;
  background: var(--cell);
  transition: background-color .18s, box-shadow .18s;
}

/* Open: a lit gate you can shove a tile through. */
.corridor.show .corridor-cell {
  box-shadow:
    inset 0 0 0 2px rgba(53,198,168,.55),
    0 0 18px rgba(53,198,168,.25);
}

/* Shut: hatched over, nothing gets through. */
.corridor.show.closed .corridor-cell {
  box-shadow: inset 0 0 0 2px rgba(226,85,95,.5);
}

.corridor.closed .corridor-cell {
  background-color: rgba(226,85,95,.16);
  background-image: repeating-linear-gradient(
    45deg,
    rgba(226,85,95,.34) 0 5px,
    rgba(226,85,95,0) 5px 11px
  );
}

/* Occupied: a tile is in the channel right now. */
.corridor.show.busy .corridor-cell {
  box-shadow:
    inset 0 0 0 2px rgba(53,198,168,.9),
    0 0 26px rgba(53,198,168,.5);
}

.corridor.busy .corridor-cell {
  background-color: rgba(53,198,168,.6);
  background-image: none;
}

/* Somebody else got there first. */
.corridor.blocked .corridor-cell {
  background-color: rgba(226,85,95,.5);
  background-image: none;
}

/* A tile in transit. Positioned in viewport space so it can fly
   from a cell on one board to a cell on the other. */
.flying-tile {
  position: fixed;
  z-index: 150;
  border-radius: 7%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 900;
  pointer-events: none;
  box-shadow: 0 6px 18px rgba(0,0,0,.28);
  transition: transform .62s cubic-bezier(.32,.86,.36,1);
}

/* =========================================================
   WAIT / OVERLAY
========================================================= */

.overlay {
  position: absolute;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(18,22,28,.85);
  backdrop-filter: blur(4px);
}

.overlay-card {
  width: min(380px, calc(100% - 32px));
  background: var(--panel);
  border-radius: 18px;
  padding: 28px;
  text-align: center;
  box-shadow: 0 24px 60px rgba(0,0,0,.55);
}

.overlay-title {
  font-size: 26px;
  font-weight: 900;
  margin-bottom: 8px;
}

.overlay-text {
  color: var(--ink-dim);
  margin-bottom: 18px;
}

#gameMessage {
  position: fixed;
  left: 50%;
  top: 50%;
  transform: translate(-50%,-50%);
  z-index: 200;
  background: var(--panel);
  color: var(--ink);
  border: 1px solid var(--line);
  padding: 18px 26px;
  border-radius: 14px;
  font-weight: 900;
  pointer-events: none;
  opacity: 0;
  transition: opacity .2s;
}

#gameMessage.show {
  opacity: 1;
}

/* =========================================================
   MOBILE
========================================================= */

@media (max-width: 700px) {

  body {
    align-items: stretch;
  }

  .topbar {
    height: 54px;
    flex-basis: 54px;
    padding: 6px calc(12px + env(safe-area-inset-right))
             6px calc(12px + env(safe-area-inset-left));
  }

  .top-title {
    font-size: 17px;
  }

  .boards {
    grid-template-columns: auto;
    grid-template-rows: auto auto;
    gap: 46px;
    padding: 0 10px calc(4px + env(safe-area-inset-bottom));
  }

  .player-header {
    padding-bottom: 3px;
  }

  .player-name {
    font-size: 14px;
  }

  .score {
    min-width: 52px;
    padding: 3px 6px;
    font-size: 9px;
  }

  .score strong {
    font-size: 13px;
  }

  /* Two boards, their headers and one corridor's worth of gap all
     have to fit the height. dvh keeps the browser chrome honest. */
  .board-wrap {
    width: min(calc((100vh - 150px) / 2.25), calc(100vw - 24px), 420px);
    width: min(calc((100dvh - 150px) / 2.25), calc(100vw - 24px), 420px);
  }

  /* Header below the lower board, so the channel between the two
     boards stays clear. */
  #player2 {
    flex-direction: column-reverse;
  }

  #player2 .player-header {
    padding-top: 3px;
    padding-bottom: 0;
  }

}

@media (max-height: 650px) and (min-width: 701px) {
  .topbar {
    height: 55px;
    flex-basis: 55px;
  }

  .board-wrap {
    width: min(100%, calc(100vh - 90px), 460px);
  }
}
