@theme-color: #6c5ce7;
@theme-color-highlighted: #8a7bf0;
@theme-color-selected: #a59bf5;
@background-color: #222629;
@dark-accent-color: #2e353b;
@card-back-color: #6c5ce7;
@card-front-color: #f7f5ff;
@match-color: #2ecc71;

@import "core.less";

#game-over-modal {
  --victory-winning-cell-color: @theme-color-highlighted;
}

body {
  color: white;
}

#gear {
  padding-right: 5px;
}

//
// players scoreboard
//

.players-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: stretch;
  gap: 10px;
  margin: 10px auto 6px auto;
  padding: 0 8px;
}

.player-info {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  border-radius: 10px;
  background-color: @dark-accent-color;
  cursor: default;
  box-sizing: border-box;
  border: 2px solid transparent;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;

  .player-name-wrap {
    display: inline-flex;
    flex-direction: column;
    align-items: flex-start;
    line-height: 1.15;
  }

  .player-pairs {
    font-size: 12px;
    font-weight: 400;
    opacity: 0.85;
  }

  &.me-player {
    background-color: lighten(@dark-accent-color, 5%);
  }

  // active player highlight
  &.memory-turn {
    border-color: @theme-color-highlighted;
    box-shadow: 0 0 12px fade(@theme-color-highlighted, 60%);
  }
}

// the current player's own seat, shown below the board
.me-row {
  margin-top: 4px;
  margin-bottom: 12px;

  .player-info {
    padding: 8px 18px;
  }
}

//
// turn status / instructions banner (below the board, above your seat)
//

.turn-status-row {
  display: flex;
  justify-content: center;
  margin: 4px auto 0 auto;
  padding: 0 8px;
  min-height: 1.5em;
}

// Matches Go Fish's instruction text: flat, centered, highlighted copy with no
// pill/badge so the two games read the same.
.memory-turn-status {
  text-align: center;
  font-size: 1rem;
  color: @theme-color-highlighted;
  padding: 8px 12px;
}

//
// board
//

#board-row {
  justify-content: center;
  // Bootstrap's .row adds negative side margins (-15px) that are normally
  // cancelled out by column padding. The board sits directly in this row with
  // no column wrapper, so those negative margins push it past both viewport
  // edges on mobile (the cards get clipped on the left and right). Zero them
  // out so the row, and therefore the board, can never be wider than the
  // viewport.
  margin-left: 0;
  margin-right: 0;
}

.memory-board {
  display: grid;
  gap: 10px;
  width: 100%;
  // Never let the board exceed the space it's given; the inline max-width set
  // in JS only ever shrinks this further on wider screens.
  max-width: 100%;
  box-sizing: border-box;
  margin: 10px auto;
  padding: 0 8px;
  justify-content: center;
}

// On phones, tighten spacing so every column fits the viewport width. Cards
// shrink to fill their tracks (minmax 0 1fr) rather than reducing the column
// count, which keeps larger boards compact in height instead of very tall.
@media (max-width: 575px) {
  .memory-board {
    gap: 6px;
    padding: 0 4px;
  }
}

@media (max-width: 400px) {
  .memory-board {
    gap: 4px;
    padding: 0 2px;
  }
}

.memory-card {
  position: relative;
  width: 100%;
  // keep cards square
  aspect-ratio: 1 / 1;
  perspective: 600px;
  cursor: pointer;
  // Solid backing behind the rotating inner. At the 90deg midpoint of a flip
  // both faces are edge-on (backface-visibility: hidden), so without this the
  // dark page background shows through and the card flashes black. The container
  // itself doesn't rotate, so this stays put and fills that gap.
  background: linear-gradient(135deg, @card-back-color, darken(@card-back-color, 18%));
  border-radius: 10px;
}

// fallback for browsers without aspect-ratio support
@supports not (aspect-ratio: 1 / 1) {
  .memory-card {
    height: 0;
    padding-bottom: 100%;
  }
  .memory-card-inner {
    position: absolute;
    top: 0;
    left: 0;
  }
}

.memory-card-inner {
  position: relative;
  width: 100%;
  height: 100%;
  transition: transform 0.4s ease, filter 0.3s ease;
  transform-style: preserve-3d;
}

.memory-card.revealed .memory-card-inner {
  transform: rotateY(180deg);
}

.memory-card-back,
.memory-card-front {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: 10px;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: border-color 0.3s ease, box-shadow 0.3s ease, background-color 0.3s ease;
}

.memory-card-back {
  background: linear-gradient(135deg, @card-back-color, darken(@card-back-color, 18%));
  border: 2px solid darken(@card-back-color, 25%);
  box-shadow: inset 0 0 0 4px fade(white, 10%);

  &::after {
    content: "?";
    font-size: 28px;
    font-weight: 700;
    color: fade(white, 70%);
  }
}

.memory-card-front {
  background-color: @card-front-color;
  border: 2px solid darken(@card-front-color, 12%);
  transform: rotateY(180deg);
  padding: 8%;
}

.memory-face {
  width: 100%;
  height: 100%;
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}

// matched cards: clearly tinted and dimmed so collected pairs stand apart from
// the plain white unmatched cards. A one-shot pop + glow celebrates the match.
.memory-card.matched {
  cursor: default;
  // Pop the whole card. Scale lives on the container (not the inner/front),
  // which carries the rotateY(180deg); animating their transform would flip the
  // card edge-on mid-pop.
  animation: memory-match-pop 0.5s ease;

  .memory-card-front {
    border-color: darken(@match-color, 6%);
    box-shadow: 0 0 12px fade(@match-color, 60%);
    // tint the face green so collected pairs clearly stand apart from the
    // plain white unmatched cards
    background-color: mix(@match-color, @card-front-color, 38%);
    // box-shadow only: safe to animate without clobbering the flip transform
    animation: memory-match-glow 0.6s ease;
  }

  // Dim with a filter rather than opacity so the card's solid backing doesn't
  // bleed through and tint the matched face.
  .memory-card-inner {
    filter: brightness(0.72);
  }
}

@keyframes memory-match-pop {
  0% { transform: scale(1); }
  45% { transform: scale(1.12); }
  100% { transform: scale(1); }
}

@keyframes memory-match-glow {
  0% { box-shadow: 0 0 12px fade(@match-color, 60%); }
  45% { box-shadow: 0 0 26px fade(@match-color, 100%); }
  100% { box-shadow: 0 0 12px fade(@match-color, 60%); }
}

// the first card flipped this turn gets a subtle highlight
.memory-card.selected .memory-card-front {
  border-color: @theme-color-highlighted;
  box-shadow: 0 0 10px fade(@theme-color-highlighted, 70%);
}

// a non-matching pair flashes red before flipping back down
.memory-card.mismatch .memory-card-front {
  border-color: #c0392b;
  box-shadow: 0 0 12px fade(#c0392b, 65%);
}

// Shake the whole card (not the front face). The front face carries the
// rotateY(180deg) that keeps it facing the viewer, so animating its transform
// clobbers that rotation and the card flips edge-on mid-shake. The container
// has no 3D transform, so shaking it is safe. Delay until the flip-up settles.
.memory-card.mismatch {
  animation: memory-mismatch-shake 0.4s ease-in-out 0.4s 1;
}

@keyframes memory-mismatch-shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-4px); }
  40% { transform: translateX(4px); }
  60% { transform: translateX(-3px); }
  80% { transform: translateX(3px); }
}

// hover affordance only for face-down, clickable cards
.memory-card:not(.revealed):hover .memory-card-back {
  border-color: @theme-color-highlighted;
  box-shadow: 0 0 10px fade(@theme-color-highlighted, 60%);
}

// spectators and out-of-turn players shouldn't see a clickable affordance
body.spectator-mode .memory-card {
  cursor: default;
}

// demo board is dimmed to signal it's a preview
body .game-info.dim {
  opacity: 0.6;
}

//
// lobby layout
//

// Mirror the in-game layout in the lobby: the board is rendered face down (see
// memory.js), the other players sit above it, and the current player's seat sits
// below it, just like once the game starts (and like Connect 4's empty lobby
// board). We only reorder the rows after the board so the host's board size
// selector sits just above the player's seat, with the start controls at the
// bottom.
body.memory-lobby #bodyContent {
  display: flex;
  flex-direction: column;
}

body.memory-lobby #board-row { order: 10; }
body.memory-lobby #memory-lobby-options-row { order: 11; }
body.memory-lobby #me-row { order: 12; }
body.memory-lobby #turn-status-row { order: 13; }
body.memory-lobby #sharing-link-row { order: 14; }
body.memory-lobby #get-started-block { order: 15; }
body.memory-lobby #bodyContent > .bottom-buffer { order: 16; }

// The lobby board is only a face-down preview; it isn't interactive yet.
body.memory-lobby #board .memory-card {
  pointer-events: none;
  cursor: default;
}

//
// lobby: host board size selector
//

#memory-lobby-options-row {
  margin-top: 10px;
  justify-content: center;
}

.memory-lobby-options {
  background-color: @dark-accent-color;
  border-radius: 8px;
  padding: 12px 16px;
  text-align: center;
}

.memory-options-label {
  display: block;
  font-weight: 700;
  margin-bottom: 6px;
  color: @theme-color-selected;
}

#memory-pairs-select {
  max-width: 240px;
  margin: 0 auto;
}
