/* Reflex Chess -- the coordinates trainer at /coordinates.
 *
 * Loaded after seo.css and inherits every token from it: --sq-light,
 * --sq-dark, --card, --rule, --brand, --good, --bad. Nothing here redefines a
 * colour, so the tool follows the page into light mode without knowing that
 * light mode exists.
 *
 * THE ONE RULE THIS FILE EXISTS TO ENFORCE: nothing in the trainer may change
 * size when the question changes. The prompt line, the answer readout, the
 * feedback line, the clock and the score all have a height that is set once and
 * never depends on their contents -- "Tap this square / e4" and "Round over /
 * 24" occupy exactly the same box. A board that jumps a centimetre down the
 * page between two prompts costs the user the tap they were already making.
 */

#ct {
  margin: 1.6rem 0 2.4rem;
  padding: 1rem 1rem 1.15rem;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
}

#ct h2 { margin-top: 0; }

/* ---------- controls ---------- */

.ct-controls { display: grid; gap: .7rem; margin-bottom: 1rem; }

.ct-row > .lab {
  display: block;
  font-size: .74rem;
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--dim);
  margin-bottom: .3rem;
}

.seg {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: .25rem;
  background: var(--card-2);
  border: 1px solid var(--rule);
  border-radius: .8rem;
  padding: .25rem;
}

.seg button {
  font: inherit;
  font-size: .92rem;
  font-weight: 600;
  line-height: 1.2;
  color: var(--dim);
  background: transparent;
  border: 0;
  border-radius: .6rem;
  /* 2.85rem is a 45px target at the default root size. Below that this is a
     game of thumb roulette on a phone. */
  min-height: 2.85rem;
  padding: .4rem .25rem;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.seg button:hover { color: var(--ink); }
.seg button[aria-pressed="true"] { background: var(--brand); color: #fff; }
.seg button:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }

/* The side switch is the headline control on this page -- naming squares from
   Black's side is the thing people come here unable to do -- so it is taller
   than the rest and carries a swatch of the colour it means. */
.ct-side button { min-height: 3.2rem; font-size: 1rem; }

.ct-side button::before {
  content: "";
  display: inline-block;
  vertical-align: -.12em;
  width: .82em;
  height: .82em;
  margin-right: .42em;
  border-radius: .18em;
  border: 1px solid var(--rule);
  background: var(--sq-light);
}

.ct-side button[data-val="black"]::before { background: #23262f; border-color: #23262f; }
.ct-side button[data-val="mixed"]::before {
  background: linear-gradient(135deg, var(--sq-light) 0 50%, #23262f 50% 100%);
}

.ct-opts { margin-top: .15rem; }

.ct-opts > summary {
  cursor: pointer;
  font-size: .88rem;
  font-weight: 600;
  color: var(--dim);
  list-style: none;
  padding: .25rem 0;
}

.ct-opts > summary::-webkit-details-marker { display: none; }
.ct-opts > summary::before { content: "\25B8\00a0"; }
.ct-opts[open] > summary::before { content: "\25BE\00a0"; }
.ct-opts .ct-controls { margin: .7rem 0 0; }

.ct-check {
  display: flex;
  align-items: center;
  gap: .6rem;
  font-size: .95rem;
  min-height: 2.6rem;
  cursor: pointer;
}

.ct-check input { width: 1.15rem; height: 1.15rem; accent-color: var(--brand); flex: none; }
.ct-check em { font-style: normal; color: var(--dim); font-size: .84rem; }

/* ---------- the stage ---------- */

.ct-stage { max-width: 23rem; margin: 0 auto; }

/* Which way round the board is, stated in words as well as drawn, because in
   mixed mode it changes under you every question and the corner you are about
   to tap depends on it. Fixed height: "From White's side" and "From Black's
   side" must occupy the same box. */
.ct-orient {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  height: 1.7rem;
  font-size: .88rem;
  font-weight: 700;
  color: var(--ink);
}

.ct-orient::before {
  content: "";
  width: .8em;
  height: .8em;
  border-radius: .18em;
  border: 1px solid var(--rule);
  background: var(--sq-light);
}

.ct-orient[data-side="black"]::before { background: #23262f; border-color: #4a4f63; }

.ct-prompt {
  display: grid;
  grid-template-rows: 1.3rem 3rem;
  place-items: center;
  text-align: center;
  margin-bottom: .3rem;
}

.ct-prompt .lab {
  font-size: .78rem;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--dim);
  line-height: 1.3rem;
}

/* Fixed box, contents centred inside it. The font-size of the value legally
   varies -- "Find" is set smaller than "e4" -- and the row height does not. */
.ct-prompt .val {
  display: grid;
  place-items: center;
  width: 100%;
  height: 3rem;
  font-size: 2.5rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: .01em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.ct-prompt .val.dim { font-size: 1.5rem; font-weight: 600; color: var(--dim); }

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

.ct-board {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  aspect-ratio: 1 / 1;
  width: 100%;
  border-radius: .5rem;
  overflow: hidden;
  border: 1px solid var(--rule);
  /* A tap on a square must never be read as a double-tap zoom or start a text
     selection: both make the board feel broken on a phone. */
  touch-action: manipulation;
  user-select: none;
  -webkit-user-select: none;
}

.ct-board .sq {
  position: relative;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition: background-color .12s;
}

.ct-board .sq.light { background: var(--sq-light); }
.ct-board .sq.dark  { background: var(--sq-dark); }

/* Edge labels, the way a printed board carries them: files along the bottom
   row, ranks up the left column -- which squares those are depends on which
   way round the board is, so they are stamped from the square name itself. */
.ct-board .sq[data-rank]::before,
.ct-board .sq[data-file]::after {
  position: absolute;
  font-size: .58rem;
  font-weight: 700;
  line-height: 1;
  opacity: .85;
  pointer-events: none;
}

.ct-board .sq[data-rank]::before { content: attr(data-rank); top: .18em; left: .3em; }
.ct-board .sq[data-file]::after  { content: attr(data-file); right: .3em; bottom: .22em; }

.ct-board .sq.light::before, .ct-board .sq.light::after { color: var(--sq-dark); }
.ct-board .sq.dark::before,  .ct-board .sq.dark::after  { color: var(--sq-light); }

/* Hiding these is the whole exercise, and it is one class. */
.ct-board.nolabels .sq::before, .ct-board.nolabels .sq::after { content: none; }

.ct-board .sq:focus-visible { outline: 3px solid var(--ink); outline-offset: -3px; z-index: 2; }

/* The square being asked about in name-the-square mode. A ring rather than a
   fill, so the square's own colour stays readable -- half the point of the
   exercise is knowing that c4 is light. */
.ct-board .sq.ask { box-shadow: inset 0 0 0 .3rem var(--brand); z-index: 1; }
.ct-board .sq.ask::after, .ct-board .sq.ask::before { opacity: .35; }

.ct-board .sq.hit  { background: var(--good); box-shadow: inset 0 0 0 .18rem rgb(0 0 0 / .18); }
.ct-board .sq.miss { background: var(--bad);  box-shadow: inset 0 0 0 .18rem rgb(0 0 0 / .18); }
.ct-board .sq.hit::before, .ct-board .sq.hit::after,
.ct-board .sq.miss::before, .ct-board .sq.miss::after { color: rgb(0 0 0 / .5); }

/* ---------- feedback ---------- */

/* THREE lines' worth, and a fixed height rather than a min-height, because a
   min-height only reserves space until something longer turns up. Measured: at
   390px the end-of-round line ("24 correct, 6 missed (80% right). New best for
   these settings.") wraps to three lines and grew this box by 19px on a
   min-height of 2.8rem, which moved the clock and the score down the page in
   the same instant the user was reading them. */
.ct-feedback {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  height: 4.2rem;
  overflow: hidden;
  margin: 0;
  padding: .2rem .4rem;
  font-size: .88rem;
  line-height: 1.35;
  color: var(--dim);
}

/* ---------- answer pad ---------- */

#ct-pad { display: none; }
#ct.mode-name #ct-pad { display: grid; gap: .35rem; margin-top: .1rem; }

.padrow { display: grid; grid-template-columns: repeat(8, 1fr); gap: .3rem; }

.padkey {
  font: inherit;
  font-size: 1.05rem;
  font-weight: 700;
  min-height: 2.9rem;
  color: var(--ink);
  background: var(--card-2);
  border: 1px solid var(--rule);
  border-radius: .5rem;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.padkey:hover { background: var(--brand); border-color: var(--brand); color: #fff; }
.padkey:active { transform: translateY(1px); }
.padkey:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }

/* ---------- clock, score, best ---------- */

.ct-bar {
  height: .34rem;
  margin: .8rem 0 .7rem;
  background: var(--rule);
  border-radius: 999px;
  overflow: hidden;
}

.ct-bar i { display: block; height: 100%; width: 100%; background: var(--brand); transition: width .12s linear; }

.ct-hud {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: .4rem;
  text-align: center;
}

.ct-hud div {
  background: var(--card-2);
  border: 1px solid var(--rule);
  border-radius: .6rem;
  padding: .45rem .2rem .5rem;
}

.ct-hud .k {
  display: block;
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--dim);
}

/* tabular-nums plus a fixed height is what stops the clock shoving the score
   sideways every time it ticks past a digit boundary. */
.ct-hud .v {
  display: block;
  height: 1.7rem;
  line-height: 1.7rem;
  font-size: 1.35rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

/* ---------- start ---------- */

.ct-start {
  display: block;
  width: 100%;
  margin-top: .85rem;
  padding: .85rem 1.2rem;
  font: inherit;
  font-size: 1.05rem;
  font-weight: 700;
  color: #fff;
  background: var(--brand);
  border: 0;
  border-radius: 999px;
  box-shadow: 0 var(--shelf) 0 rgb(0 0 0 / .28);
  cursor: pointer;
  touch-action: manipulation;
  transition: transform .06s, box-shadow .06s;
}

.ct-start:active { transform: translateY(var(--shelf)); box-shadow: 0 0 0 rgb(0 0 0 / .28); }
.ct-start:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

.ct-hint { margin: .8rem 0 0; font-size: .82rem; color: var(--dim); text-align: center; }

/* The module adds .live to #ct as its first act. Until then, and forever if
   JavaScript is off or the file 404s, the controls and the board are hidden and
   one sentence explains why -- rather than an empty 8x8 box that looks like a
   bug and a row of buttons that do nothing. The prose below is the page's real
   content and does not need any of this. */
#ct .ct-fallback { margin: 0; font-size: .9rem; color: var(--dim); }
#ct.live .ct-fallback { display: none; }
#ct:not(.live) .ct-controls,
#ct:not(.live) .ct-opts,
#ct:not(.live) .ct-stage { display: none; }

/* Phones: the card goes edge to edge. The trade is a lost 2.3rem of border
   radius against 5px on every square, and on a 390px screen the board is the
   only thing on this page that anyone has to hit accurately. -1.15rem is
   exactly .wrap's padding, so this reaches the viewport edge and no further --
   a fraction more and the whole document scrolls sideways. */
@media (max-width: 34rem) {
  #ct {
    margin-inline: -1.15rem;
    padding: .9rem .9rem 1.1rem;
    border-radius: 0;
    border-left: 0;
    border-right: 0;
  }
  .seg button { font-size: .88rem; }
}

@media (max-width: 22rem) {
  .seg button { font-size: .8rem; }
  .ct-side button { font-size: .9rem; }
}

@media print {
  #ct { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .ct-board .sq, .ct-bar i, .ct-start { transition: none; }
}
