/* Torre di Hanoi board. Inherits the existing theme tokens (--text, --muted, --line, --accent,
   --action-text, --canvas). */
.hanoi { display: grid; justify-items: center; gap: .9rem; width: min(100%, 32rem); margin-inline: auto; color: inherit; }
/* One column per peg, so a three-peg board and a four-peg one need one rule between them. The
   disc height is the unit everything else is measured in: a peg is one row taller than its own
   tower, which is the room a lifted disc needs above it. */
.hanoi-board { --disc-h: clamp(16px, 4.6vw, 24px); display: grid; grid-template-columns: repeat(var(--pegs, 3), minmax(0, 1fr)); gap: .4rem; width: 100%; }
.hanoi-peg, .hanoi-goal-peg { --floor: 1.5rem; position: relative; height: calc(var(--rows, 4) * var(--disc-h) + var(--floor)); }
.hanoi-peg { min-width: 0; margin: 0; padding: 0; font: inherit; color: inherit; background: transparent; border: 0; border-radius: .4rem; cursor: pointer; }
/* The stand each peg is planted in, drawn per peg so a board of three and a board of four both
   sit on something without the board itself knowing how many there are. */
.hanoi-peg::before, .hanoi-goal-peg::before { content: ""; position: absolute; left: 2%; right: 2%; bottom: var(--floor); height: 3px; background: var(--line, #c2ccbd); border-radius: 2px; }
.hanoi-post { position: absolute; left: 50%; top: 0; bottom: var(--floor); width: 4px; transform: translateX(-50%); background: var(--line, #c2ccbd); border-radius: 2px; }
/* Discs pack to the bottom of the post and grow upwards, which is why the stack spans the whole
   peg rather than only what is in it: a disc in hand is drawn at the top of the same box. */
.hanoi-stack { position: absolute; left: 0; right: 0; top: 0; bottom: calc(var(--floor) + 3px); display: flex; flex-direction: column-reverse; justify-content: flex-start; align-items: center; }
/* A disc's width is its size against the largest on the board, which is the only thing that
   distinguishes one from another on a real one. The number is printed as well, because a width
   is not something a screen reader or a hurried eye can compare. */
.hanoi-disc { box-sizing: border-box; display: grid; place-items: center; width: calc(100% * var(--size, 1) / var(--discs, 3)); min-width: 20px; height: var(--disc-h); margin: 1px 0; font-size: calc(var(--disc-h) * .52); font-weight: 600; font-variant-numeric: tabular-nums; line-height: 1; color: var(--action-text, #fff); background: var(--accent, currentColor); border-radius: calc(var(--disc-h) / 2); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--text, currentColor) 20%, transparent); }
/* In hand: out of the stack and at the top of its own post, which is what picking one up looks
   like. It stays on the peg it came from until it is set down somewhere. */
.hanoi-disc.is-lifted { position: absolute; top: 0; left: 50%; transform: translateX(-50%); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--text, currentColor) 20%, transparent), 0 3px 0 color-mix(in srgb, var(--text, currentColor) 22%, transparent); }
.hanoi-peg.is-lifted { background: color-mix(in srgb, var(--text, currentColor) 8%, transparent); }
.hanoi-peg.is-target { background: color-mix(in srgb, var(--accent, currentColor) 14%, transparent); }
.hanoi-peg.is-target .hanoi-post { background: var(--accent, currentColor); }
.hanoi-peg:hover:not([aria-disabled="true"]) .hanoi-post { background: var(--accent, currentColor); }
.hanoi-peg:focus-visible { outline: 3px solid var(--text, currentColor); outline-offset: 2px; }
.hanoi-peg[aria-disabled="true"] { cursor: default; }
.hanoi-name { position: absolute; left: 0; right: 0; bottom: 0; height: var(--floor); font-size: .8125rem; line-height: var(--floor); text-align: center; color: var(--muted, currentColor); }
.hanoi-choice { min-height: 1.4rem; max-width: 34rem; margin: 0; font-size: .9375rem; line-height: 1.4; text-align: center; color: var(--muted, currentColor); }
.hanoi-choice[data-holding="true"], .hanoi-choice[data-refused="true"] { color: var(--text, currentColor); }
/* The ending, at a size that reads as a caption rather than a second board. It is the same
   markup as the board above it, one unit smaller and with nothing to press. */
.hanoi-goal { display: grid; justify-items: center; gap: .35rem; margin: 0; }
.hanoi-goal-board { --disc-h: clamp(9px, 2.4vw, 13px); display: grid; grid-template-columns: repeat(var(--pegs, 3), minmax(0, 1fr)); gap: .3rem; width: min(100%, 15rem); }
.hanoi-goal-peg { --floor: 4px; }
.hanoi-goal .hanoi-disc { min-width: 12px; font-size: 0; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--text, currentColor) 20%, transparent); }
.hanoi-goal-caption { font-size: .8125rem; color: var(--muted, currentColor); }
.hanoi-tally { display: flex; flex-wrap: wrap; justify-content: center; gap: .4rem 1.75rem; margin: 0; font-size: .875rem; }
.hanoi-metric { display: inline-flex; align-items: baseline; gap: .5rem; }
.hanoi-label { color: var(--muted, currentColor); }
.hanoi-value { font-size: var(--type-title); font-variant-numeric: tabular-nums; }
.hanoi-hint { max-width: 34rem; margin: 0; font-size: .875rem; line-height: 1.5; text-align: center; color: var(--muted, currentColor); }
.hanoi[data-state="solved"] .hanoi-peg { background: color-mix(in srgb, var(--accent, currentColor) 12%, transparent); }
.hanoi[data-state="blocked"] .hanoi-peg, .hanoi[data-state="waiting"] .hanoi-peg { cursor: default; }
@media (prefers-reduced-motion: no-preference) {
  .hanoi-disc { transition: width .18s ease; }
  .hanoi-peg { transition: background-color .18s ease; }
}
@media (max-width: 380px) {
  .hanoi { gap: .7rem; width: 100%; }
  .hanoi-board { --disc-h: 16px; gap: .25rem; }
  .hanoi-disc { min-width: 16px; }
  .hanoi-tally { gap: .3rem 1.1rem; }
}
@media (forced-colors: active) {
  .hanoi-post, .hanoi-peg::before, .hanoi-goal-peg::before { background: CanvasText; }
  .hanoi-disc { color: Canvas; background: CanvasText; }
  .hanoi-peg.is-target, .hanoi-peg.is-lifted { background: Highlight; }
}
