/* ==========================================================================
   dots-and-boxes.css — dots and boxes' arena
   (src/assets/js/games/dots-and-boxes/view.mjs), inside the table games.css
   draws: a square of round dots, a real line for every line drawn, and its
   claimer's initial in every box. Every line of the board is a button, drawn
   or not. Every class here is .db-*.
   ========================================================================== */

/* The column the board is given is its measure (cqw, below): the widest board still fits a phone. */
.db {
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* The board is a lattice of 2n + 1 rows and columns: a dot where both are even, a box where both
   are odd, a line between two dots everywhere else. One measure sets it, --pitch, the step from dot
   to dot: 72 design pixels where there is room, less in a narrow column. A board is n pitches wide
   and each rim line can be pressed --reach further out, so the whole of it — n pitches and two
   reaches — is what must fit: 343px at 5 × 5 in the 343px column of a 375px phone (59.8px from dot
   to dot). The first --pitch is for a browser without container units. */
.db-board {
  --n: 4; /* boxes a side; view.mjs sets it */
  --dot: calc(9 * var(--s, 1px));
  --stroke: calc(3 * var(--s, 1px)); /* a drawn line; an odd count like the dot's, so it sits on whole pixels */
  --inset: calc(4 * var(--s, 1px)); /* a line's own box stops this short of its dots: the focus ring clears them */
  --press: calc(22 * var(--s, 1px)); /* how far to either side of a line a press still finds it */
  --pitch: min(calc(72 * var(--s, 1px)), calc((100vw - 40px - 2 * var(--press)) / var(--n)));
  --reach: min(var(--press), calc(var(--pitch) / 2));
  display: grid;
  grid-template-columns: repeat(var(--n), var(--dot) calc(var(--pitch) - var(--dot))) var(--dot);
  grid-template-rows: repeat(var(--n), var(--dot) calc(var(--pitch) - var(--dot))) var(--dot);
  /* The rim lines' targets stay inside the board's own box at the sides and below, so nothing
     reaches past the column or onto the legend. Above, they lie in the arena's own padding: a
     phone's screen has no height to spare (the feedback line under a 4 × 4 board has to show). */
  padding: 0 calc(var(--reach) - var(--dot) / 2) calc(var(--reach) - var(--dot) / 2);
  -webkit-user-select: none;
  user-select: none;
}
@supports (width: 1cqw) {
  .db-board { --pitch: min(calc(72 * var(--s, 1px)), calc((100cqw - 2 * var(--press)) / var(--n))); }
}

/* A dot: round, ink, and above the lines that end under it. While the turn is someone else's the
   dots still free go grey with the rest of what the board offers (the tracks, below); what has
   been drawn — the lines, the dots they join (view.mjs marks those), the boxes' marks — keeps its
   ink throughout. */
.db-dot {
  position: relative;
  z-index: 2;
  border-radius: 50%;
  background: var(--ink-muted);
  transition: background-color 150ms ease;
}
.db-dot--on,
.db-board--live .db-dot,
.db-board--over .db-dot { background: var(--ink); }

/* A line: a button from the start, lying between its two dots. Its own box is the slot between
   them, which is what the focus ring goes round; ::after is the stroke, from the middle of one dot
   to the middle of the other, and ::before is what a press finds. --w and --line are the stroke's
   weight and colour, set by the states below. */
.db-line {
  --w: 1px;
  --line: transparent;
  position: relative;
  -webkit-appearance: none;
  appearance: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  cursor: default;
  -webkit-tap-highlight-color: transparent;
}
.db-line--h { margin-inline: var(--inset); }
.db-line--v { margin-block: var(--inset); }
.db-line::after {
  content: "";
  position: absolute;
  background: var(--line);
  transition: background-color 150ms ease;
}
.db-line--h::after {
  inset-inline: calc(var(--dot) / -2 - var(--inset));
  inset-block-start: calc(50% - var(--w) / 2);
  block-size: var(--w);
}
.db-line--v::after {
  inset-block: calc(var(--dot) / -2 - var(--inset));
  inset-inline-start: calc(50% - var(--w) / 2);
  inline-size: var(--w);
}
/* What a press finds: everything nearer this line than any other, out to --reach on either side.
   A long hexagon from dot to dot, tapering to a point at each, so the targets of two lines never
   overlap and the middle of a box, where its mark goes, is nobody's. Above the buttons' own boxes
   and under the dots: a press on a dot itself, as near one line as another, draws nothing. */
.db-line::before {
  content: "";
  position: absolute;
  z-index: 1;
}
.db-line--h::before {
  inset: calc(var(--dot) / 2 - var(--reach)) calc(var(--dot) / -2 - var(--inset));
  clip-path: polygon(0 50%, var(--reach) 0, calc(100% - var(--reach)) 0, 100% 50%, calc(100% - var(--reach)) 100%, var(--reach) 100%);
}
.db-line--v::before {
  inset: calc(var(--dot) / -2 - var(--inset)) calc(var(--dot) / 2 - var(--reach));
  clip-path: polygon(50% 0, 100% var(--reach), 100% calc(100% - var(--reach)), 50% 100%, 0 calc(100% - var(--reach)), 0 var(--reach));
}

/* On your turn every line still to be drawn shows as a hairline track — where a line can go, for a
   phone with no pointer to find it by — and under the keyboard's focus as a grey ghost of the line
   it would be, inside the ring; under the pointer it is pink (only where there is a hover). While
   the turn is someone else's there are no tracks at all: nothing that cannot be pressed looks as
   if it could. */
.db-board--live .db-line:not(.db-line--drawn) {
  --line: var(--hairline);
  cursor: pointer;
}
.db-board--live .db-line:not(.db-line--drawn):focus-visible {
  --w: var(--stroke);
  --line: color-mix(in srgb, var(--ink-muted) 45%, transparent);
}
@media (hover: hover) {
  .db-board--live .db-line:not(.db-line--drawn):hover {
    --w: var(--stroke);
    --line: var(--pink);
  }
}
/* A line drawn: solid ink, three times a track's weight. The one just drawn is green, and a
   little heavier (so it is not its colour alone that tells it), until the next move. */
.db-line--drawn {
  --w: var(--stroke);
  --line: var(--ink);
}
.db-line--last {
  --w: calc(var(--stroke) + 2 * var(--s, 1px));
  --line: var(--green);
}
/* Someone else's line arriving grows out from its middle, so the eye finds it (view.mjs adds this
   on the move that drew it, and on no other render). Your own is simply there: it was under your
   finger. */
.db-line--h.db-line--in::after { animation: db-draw-h 200ms ease-out; }
.db-line--v.db-line--in::after { animation: db-draw-v 200ms ease-out; }
@keyframes db-draw-h {
  from { scale: 0 1; }
}
@keyframes db-draw-v {
  from { scale: 1 0; }
}

/* A box's mark: its claimer's initial, in the middle. Yours in ink and weight, the others' grey,
   and the ones just claimed green, on a touch of green (view.mjs: from the move that took them
   until the turn has passed and the next seat has moved). */
.db-box {
  display: grid;
  place-items: center;
  font-family: var(--font-mono);
  font-size: calc(var(--pitch) * 0.34);
  line-height: 1;
  color: var(--ink-muted);
  transition:
    color 150ms ease,
    background-color 150ms ease;
}
.db-box--mine {
  color: var(--ink);
  font-weight: 600;
}
.db-box--last {
  color: var(--green);
  background: color-mix(in srgb, var(--green) 10%, transparent);
}
/* A mark arriving (view.mjs adds this on the move that claimed the box, and on no other render). */
.db-box--in { animation: db-in 220ms ease-out; }
@keyframes db-in {
  from {
    opacity: 0;
    scale: 0.7;
  }
}
@media (prefers-reduced-motion: reduce) {
  .db-line--in::after,
  .db-box--in { animation: none !important; }
}

/* Whose mark is whose, under the board: each mark in a small box of its own, as it stands on the
   board — yours in ink and weight — and the name it belongs to. A line of its own from the first
   move to the last, so nothing below it shifts. */
.db-legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: calc(6 * var(--s, 1px)) 2.2ch;
  margin-top: calc(4.5 * var(--s, 1px)); /* with the half pixel under the board, a whole number of them */
}
.db-key {
  display: inline-flex;
  align-items: center;
  gap: 0.8ch;
  white-space: nowrap;
}
.db-mark {
  display: inline-grid;
  place-items: center;
  box-sizing: border-box;
  inline-size: calc(20 * var(--s, 1px));
  block-size: calc(20 * var(--s, 1px));
  border: 1px solid var(--hairline);
  line-height: 1;
}
.db-key--mine { color: var(--ink); }
.db-key--mine .db-mark { font-weight: 600; }
/* The keys, where a keyboard is likely (as 24 shows its own during the count-in). */
.db-keys {
  display: none;
  margin-top: calc(10 * var(--s, 1px));
  font-size: calc(12 * var(--s, 1px));
}
@media (hover: hover) and (pointer: fine) {
  .db-keys { display: block; }
}
