/* The board and the rack — the component CSS for public/js/board-view.js.
 *
 * Every colour here comes from a custom property defined in base.css; nothing
 * in this file hardcodes one, so the light/dark toggle keeps working without
 * this file knowing that it exists.
 *
 * Sizing: the board is a square that fills whatever it is given
 * (`width: 100%` + `aspect-ratio: 1`) and is its own container query context,
 * so the letters, point values and bonus labels scale off the board's own
 * width in `cqw` rather than off the viewport or a fixed font size. That is
 * what keeps it usable on a phone and stops it ever pushing the page sideways.
 * Container queries are baseline across browsers (Chrome 105, Safari 16,
 * Firefox 110); this project targets modern browsers only and has no build
 * step to polyfill anything anyway.
 *
 * Tiles are used at two very different sizes (on the board, and in the rack),
 * so `.tile` never sets a font size directly: it reads --letter-size and
 * --pts-size, which the two containers set for it.
 */

/* --- the board ------------------------------------------------------------- */

.board {
  container-type: inline-size;

  display: grid;
  grid-template-columns: repeat(15, 1fr);
  grid-template-rows: repeat(15, 1fr);
  gap: 1px;

  width: 100%;
  max-width: 100%;
  aspect-ratio: 1;
  padding: 1px;
  /* The background shows through the 1px grid gap; that *is* the grid lines. */
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  /* No double-tap-to-zoom lag on the squares. */
  touch-action: manipulation;
  user-select: none;

  --letter-size: 3.6cqw;
  --pts-size: 1.8cqw;
}

/* On a narrow phone, base.css's body padding (0.75rem each side) costs the board 1.5rem of width
 * it can't spare — letters/point-values/bonus labels are all sized in cqw off the board's own
 * container width, so that padding shrinks every one of them too, not just the board's outline.
 * Break the board out to the full viewport width here specifically (negative margins matching
 * body's own padding, undoing it for this one element) rather than removing body's padding
 * globally — everything else on this page (the rack, scoreboard, notices, cards) already has its
 * own visible border/background, so it reads as a deliberate card either way; the board has
 * neither, so it reads as wasted margin instead. 480px is a plain "phone-sized" cutoff, not tied
 * to a specific device. */
@media (max-width: 480px) {
  .board {
    width: calc(100% + 1.5rem);
    max-width: calc(100% + 1.5rem);
    margin-left: -0.75rem;
    margin-right: -0.75rem;
    border-radius: 0;
    border-left: none;
    border-right: none;
  }
}

/* Squares are <button>s, so base.css's accent-coloured button rule has to be
 * undone in full before anything else here applies. */
.sq {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  min-height: 0;
  padding: 0;
  overflow: hidden;
  font: inherit;
  border: 0;
  border-radius: 1px;
  background: var(--sq-plain);
  color: var(--sq-fg);
  cursor: pointer;
}

.sq .bonus-label {
  font-size: var(--pts-size);
  font-weight: 700;
  letter-spacing: 0.02em;
  opacity: 0.85;
}

/* A tile hides whatever the square underneath says. */
.sq.filled .bonus-label,
.sq.filled::before {
  display: none;
}

.sq.bonus-dl { background: var(--sq-dl); }
.sq.bonus-tl { background: var(--sq-tl); color: var(--sq-fg-strong); }
.sq.bonus-dw { background: var(--sq-dw); }
.sq.bonus-tw { background: var(--sq-tw); color: var(--sq-fg-strong); }

/* The centre is a *plain* square in Wordfeud's layout — it carries no word
 * multiplier at all — but the first move has to cover it, so it gets a mark of
 * its own rather than a bonus label it does not deserve. */
.sq.center { background: var(--sq-center); }
.sq.center::before {
  content: "";
  position: absolute;
  width: 2.8cqw;
  height: 2.8cqw;
  border-radius: 50%;
  background: var(--sq-fg);
  opacity: 0.4;
}

/* Where the tile in hand could go. */
.sq.target {
  box-shadow: inset 0 0 0 2px var(--accent);
}

.sq:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  z-index: 1;
}

/* Not your turn: still perfectly readable — you need to study the position
 * while you wait — but nothing here responds to a click any more. */
.board.inert .sq {
  cursor: default;
}

/* --- tiles ----------------------------------------------------------------- */

.tile {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--tile-bg);
  color: var(--tile-fg);
  border: 1px solid var(--tile-edge);
  border-radius: 2px;
}

.tile .letter {
  font-size: var(--letter-size);
  font-weight: 600;
  line-height: 1;
}

.tile .pts {
  position: absolute;
  right: 6%;
  bottom: 4%;
  font-size: var(--pts-size);
  line-height: 1;
  opacity: 0.75;
}

/* This turn's own tiles: not committed to anything until Submit. */
.tile.pending {
  background: var(--tile-pending);
  box-shadow: inset 0 0 0 1px var(--accent);
}

/* The opponent's move, placed but not yet accepted or challenged. Dashed and
 * faded because it is a proposal, not a fact on the board. */
.tile.ghost {
  opacity: 0.6;
  border-style: dashed;
  border-width: 2px;
  border-color: var(--accent);
}

/* A blank scores nothing whatever letter it stands for, so it must be
 * unmistakable at a glance — dotted edge as well as the muted letter, since
 * colour alone is not a signal everyone can read. */
.tile.blank {
  border-style: dotted;
  border-width: 2px;
  border-color: var(--tile-blank-fg);
}
.tile.blank .letter {
  color: var(--tile-blank-fg);
  font-style: italic;
}

/* --- the rack -------------------------------------------------------------- */

.rack {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  padding: 0.4rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
  user-select: none;

  /* Rack tiles are a fixed comfortable tap size, not a fraction of anything,
   * so they measure in rem where the board's measure in cqw. */
  --letter-size: 1.4rem;
  --pts-size: 0.6rem;
}

.rack-tile {
  position: relative;
  width: 2.75rem;
  height: 2.75rem;
  flex: none;
  padding: 0;
  font: inherit;
  border: 0;
  border-radius: 3px;
  background: transparent;
  cursor: pointer;
  touch-action: manipulation;
}

.rack-tile.selected {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* A placed tile leaves its slot behind rather than closing the gap: the rack
 * shifting under the player's finger mid-move is worse than a hole in it. */
.rack-tile.used .tile {
  opacity: 0.2;
  border-style: dashed;
}

.rack-tile:disabled {
  cursor: default;
}

.rack-tile:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.rack.inert {
  opacity: 0.6;
}

@media (max-width: 380px) {
  .rack-tile {
    width: 2.4rem;
    height: 2.4rem;
  }
  .rack { --letter-size: 1.2rem; }
}

/* --- touch drag (board-view.js, TODO.md "Ready to implement" item 13) ---------------------------
 * The floating tile a touch drag follows with a finger — a native HTML5 drag
 * gets this for free from the OS; touch has to draw it. Same size as a rack
 * tile (the one place a picked-up tile is always the same size regardless of
 * whether it came from the rack or off the board), centred under the finger,
 * and never the hit-test target itself. */
.touch-drag-ghost {
  position: fixed;
  left: 0;
  top: 0;
  width: 2.75rem;
  height: 2.75rem;
  margin-left: -1.375rem;
  margin-top: -1.375rem;
  pointer-events: none;
  z-index: 1000;
  opacity: 0.9;
  filter: drop-shadow(0 4px 8px rgb(0 0 0 / 0.35));
  --letter-size: 1.4rem;
  --pts-size: 0.6rem;
}
