/* --- the visualization trainer ---------------------------------------------

   Its own page, sharing app.css for the furniture — the bar, the colours, the
   field labels — and adding only what a drill needs. Deliberately narrow and
   centred: there is one thing to look at here, unlike the board. */

.trainer {
  max-width: 34rem;
  margin: 0 auto;
  padding: 1.5rem 1.25rem 3rem;
  display: grid;
  gap: 1.5rem;
}

.trainer__setup { display: grid; gap: 0.9rem; }

.choices { display: flex; gap: 0.4rem; flex-wrap: wrap; }

.choice {
  flex: 1 1 auto;
  padding: 0.5rem 0.9rem;
  color: var(--text-dim);
}
.choice--on {
  color: var(--accent-text);
  background: var(--accent);
  border-color: var(--accent);
}

.trainer__switches { display: flex; gap: 1.25rem; flex-wrap: wrap; }

.trainer__switch {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 0.85rem;
  color: var(--text-dim);
  cursor: pointer;
}
.trainer__switch:has(input:checked) { color: var(--text); }
/* A switch that cannot be flicked says so with its label too, or only half of
   it looks disabled. */
.trainer__switch:has(input:disabled) { color: var(--text-dim); opacity: 0.4; cursor: not-allowed; }

/* --- the drill itself --- */

.drill {
  display: grid;
  gap: 1rem;
  justify-items: center;
  padding: 1.5rem 1rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  min-height: 20rem;
  align-content: center;
}

.drill__score {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-dim);
  display: flex;
  gap: 1rem;
}
.drill__clock { color: var(--accent); }

/* The square being asked about. Large, because it is the only thing on the
   screen and it should be readable from further away than a laptop. */
.drill__prompt {
  font-size: clamp(3rem, 14vw, 5rem);
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.02em;
  min-height: 1em;
  text-align: center;
}

.drill__wrong {
  display: block;
  font-size: 1.1rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bad);
  margin-top: 0.6rem;
}

/* One announced step of the recall drill: the sentence, exactly as spoken. */
.drill__said {
  font-size: clamp(1.15rem, 4.5vw, 1.6rem);
  text-align: center;
  line-height: 1.4;
  max-width: 22rem;
}

.drill__answers { display: flex; gap: 0.6rem; flex-wrap: wrap; justify-content: center; }

.drill__answer { padding: 0.8rem 1.6rem; font-size: 1rem; }
.drill__answer--dark { background: #17150f; }

.drill__aside, .drill__blurb {
  font-size: 0.85rem;
  color: var(--text-dim);
  text-align: center;
  max-width: 24rem;
  line-height: 1.5;
  margin: 0;
}

.drill__done { display: grid; gap: 0.7rem; justify-items: center; text-align: center; }
.drill__done h2 { margin: 0; font-size: 1.2rem; }
.drill__figure { margin: 0; font-size: 1.35rem; }
.drill__again { padding: 0.7rem 2rem; background: var(--accent); color: var(--accent-text); border-color: var(--accent); }

/* --- a board of any size --- */

.board {
  display: grid;
  grid-template-columns: repeat(var(--files, 8), 1fr);
  /* Rows have to be stated too. Left to size themselves they take their
     height from what is in them, so the one row holding a piece grew and the
     empty ones stayed short — a board whose squares were different sizes
     depending on whether anything was standing on them. */
  grid-template-rows: repeat(var(--files, 8), 1fr);
  width: min(100%, 24rem);
  aspect-ratio: 1;
  border-radius: 4px;
  overflow: hidden;
  /* So the labels can size themselves against the board rather than the page. */
  container-type: inline-size;
}

.board__square {
  position: relative;
  display: grid;
  place-items: center;
  /* The grid already makes these square; this keeps them square if a piece
     is ever given a size that would otherwise push its cell out. */
  min-width: 0;
  min-height: 0;
  cursor: pointer;
}
.board__square--light { background: #d3dae3; }
.board__square--dark { background: #8b9aad; }

/* Edge labels, in the square's own ink: legible when looked for, ignorable
   when not. Sized in cqw so they stay in proportion whether the board is two
   squares across or eight. */
.board__rank, .board__file {
  position: absolute;
  /* Sized against the board rather than the page, so they stay in proportion
     from two squares across to eight — and large enough to read at a glance,
     which is the only size worth having them at. */
  font-size: clamp(0.7rem, 4.5cqw, 1.5rem);
  font-weight: 700;
  line-height: 1;
  color: rgb(0 0 0 / 0.5);
  pointer-events: none;
}
.board__rank { left: 5%; top: 4%; }
.board__file { right: 5%; bottom: 3%; }

/* On a dark square the dark ink disappears, so it flips. */
.board__square--dark .board__rank,
.board__square--dark .board__file { color: rgb(255 255 255 / 0.62); }

/* A board that is only for reference: nothing on it responds to a click, and
   it sits a little smaller so the sentence above it stays the main event. */
.board--quiet { width: min(100%, 18rem); }
.board--quiet .board__square { cursor: default; }

/* A piece arriving on a square, and one going from it. Short and small: the
   review is stepped through quickly, and a flourish would be in the way by
   the third press. The one that leaves is a copy put back for exactly as long
   as it takes to go, which is why it holds its last frame. */
@keyframes piece-arriving {
  from { opacity: 0; transform: scale(0.55); }
  to { opacity: 1; transform: scale(1); }
}
@keyframes piece-leaving {
  from { opacity: 1; transform: scale(1); }
  to { opacity: 0; transform: scale(0.55); }
}
.board piece[data-arriving] { animation: piece-arriving 220ms ease-out; }
.board piece[data-leaving] {
  /* Centred on the square by its own offsets rather than by the grid, since
     an absolutely positioned child is no longer one of the grid's items. Kept
     under anything arriving: a captured piece fades out beneath its captor. */
  position: absolute;
  inset: 0;
  margin: auto;
  width: 88%;
  z-index: 0;
  animation: piece-leaving 220ms ease-in forwards;
}

@media (prefers-reduced-motion: reduce) {
  .board piece[data-arriving], .board piece[data-leaving] { animation: none; }
}

.board__square--right { box-shadow: inset 0 0 0 3px var(--good); }
.board__square--wrong { box-shadow: inset 0 0 0 3px var(--bad); }
/* What the action being reviewed touched — including every square a
   recolouring changed, which can be several at once. */
.board__square--changed { box-shadow: inset 0 0 0 3px var(--accent); }

.board piece, .palette piece {
  display: block;
  width: 88%;
  aspect-ratio: 1;
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  pointer-events: none;
}

/* --- what may be put down --- */

/* Sized to what is in it rather than to a fixed six across: a knights-only
   drill offers three buttons, and three buttons stretched over six columns
   look like three that are missing. */
.palette {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.3rem;
  width: min(100%, 24rem);
}
.palette__pick { flex: 0 0 3rem; }

.palette__pick {
  aspect-ratio: 1;
  padding: 0.15rem;
  display: grid;
  place-items: center;
  background: var(--surface-raised);
}
.palette__pick--on { border-color: var(--accent); background: #3a3423; }
.palette__pick--rub { font-size: 1.1rem; color: var(--text-dim); }

/* --- the recall drill's settings ------------------------------------------- */

.trainer__options {
  display: grid;
  gap: 0.9rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--border);
}

/* Says what the drill does, for the parts of it that are not a setting. */
.trainer__note {
  margin: 0;
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--text-dim);
}

/* The pieces, as pieces. Five names in a row would be a list to read; five
   pictures are the thing itself. */
.roles { display: flex; gap: 0.35rem; flex-wrap: wrap; }

.role {
  flex: 1 1 3rem;
  aspect-ratio: 1;
  max-width: 3.4rem;
  display: grid;
  place-items: center;
  padding: 0.2rem;
  background: var(--surface-raised);
  opacity: 0.35;
  transition: opacity 120ms ease, border-color 120ms ease;
}
.role--on { opacity: 1; border-color: var(--accent); }
.role:disabled { cursor: not-allowed; opacity: 0.15; }
.role piece {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  pointer-events: none;
}

/* Name on one side, number on the other. The old shape put the label and the
   value in the same box, so "up to 3 pieces" wrapped into three lines and the
   two controls ran together until it was unclear which + belonged to which. */
.steppers { display: grid; gap: 0.45rem; }

.stepper {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.stepper__of { font-size: 0.85rem; color: var(--text-dim); }

/* One piece of furniture rather than three: the buttons and the number share
   a single border, so the group reads as one control. */
.stepper__control {
  flex: none;
  display: flex;
  align-items: stretch;
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
  background: var(--surface-raised);
}

.stepper__control button {
  width: 2.1rem;
  padding: 0.3rem 0;
  font-size: 1.05rem;
  line-height: 1;
  color: var(--text-dim);
  background: none;
  border: none;
  border-radius: 0;
}
.stepper__control button:hover { color: var(--text); background: #38342a; }
.stepper__control button:active { transform: none; }

.stepper__count {
  display: grid;
  place-items: center;
  /* Fixed, so the buttons do not shuffle sideways between 9 and 10. */
  min-width: 2.6rem;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  border-inline: 1px solid var(--border);
}

/* --- what the drill is made of --------------------------------------------

   The weights that actually drive the generator, shown as the shares they
   work out at. Read from the same constants the sequence is built from, so
   the table cannot drift into being a claim about the drill rather than a
   description of it. */
.weights {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.8rem;
}

.weights td {
  padding: 0.25rem 0;
  color: var(--text-dim);
  vertical-align: middle;
}
.weights td:first-child { width: 6.5rem; color: var(--text); }
.weights td:last-child { width: 2.8rem; text-align: right; font-variant-numeric: tabular-nums; }

/* The bar is the point: three numbers are a list, three bars are a shape. */
.weights__bar {
  display: block;
  height: 0.45rem;
  border-radius: 999px;
  background: var(--accent);
  min-width: 2px;
}
.weights__track { display: block; background: var(--surface-raised); border-radius: 999px; }
