/* Word Wheel — crossword, wheel, controls and dialogs.
   Sized up from the card games' chrome for the same reason jigsaw and Loose
   Ends were: the people this is for are mostly over seventy, often on a laptop
   trackpad, and a 0.92rem button they have to aim at is the difference between
   a game and a chore. Nothing here is smaller than 1rem or shorter than
   2.6rem, and the letters on the wheel are deliberately enormous. */

.word-wheel-page {
  margin: 0;

  /* Everything follows the eight site themes. Unlike Loose Ends — which has to
     pin six line colours down by hand, because two lines that look alike is a
     broken board — there is nothing here that has to stay distinguishable from
     anything else, so the whole game can simply be the site's colours. */
  --ww-cell-bg: var(--surface-alt);
  --ww-cell-shown-bg: var(--accent-soft);
  --ww-rule: var(--rule);
}


/* ------------------------------------------------------------------ shell */

.ww-shell {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 10px 12px 18px;
  /* The shell is what goes full screen, so it carries the page background
     rather than leaving a white frame round the game when it does. */
  background: var(--ground);
}

/* The dialogs' main button. The two bars that sat over the puzzle are gone:
   the dock is css/games/handheld.css, and the rest is in Menu. */
.ww-primary {
  background: var(--accent) !important;
  border-color: var(--accent) !important;
  color: var(--on-accent) !important;
  font-weight: 700;
}

.ww-primary:hover:not(:disabled) { filter: brightness(1.12); }


/* --------------------------------------------------------------- readout */

.ww-readout {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
  padding: 2px 4px;
  color: var(--ink-muted);
}

.ww-readout b {
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.ww-readout__tag { margin-left: auto; font-variant-numeric: tabular-nums; }


/* ------------------------------------------------------------------- play */

/* Crossword beside wheel on anything wide enough, crossword above wheel when
   it is not. The wheel goes SECOND in both, and that is the important half:
   it is the thing being touched, so on a phone it belongs at the bottom, near
   the thumb, with the grid above it where it can be read. */
.ww-play {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 18px 28px;
}

.ww-board {
  flex: 1 1 22rem;
  display: flex;
  justify-content: center;
}

.ww-grid {
  display: grid;
  grid-template-columns: repeat(var(--ww-cols), var(--ww-cell));
  grid-template-rows: repeat(var(--ww-rows), var(--ww-cell));
  gap: 3px;

  /* Sized off the viewport rather than off the parent, because the parent is
     a flex item whose width depends on this and the sum would be circular.
     Both terms matter: a nine column grid is limited by width, an eleven row
     one by height, and whichever bites first is the one that keeps the whole
     board on the screen without scrolling. */
  --ww-cell: clamp(1.4rem,
                   min(calc(44vw / var(--ww-cols)), calc(46vh / var(--ww-rows))),
                   3.1rem);
}

.ww-cell {
  display: grid;
  place-items: center;
  border: 1px solid var(--ww-rule);
  border-radius: 5px;
  background: var(--ww-cell-bg);
  font-family: var(--font-head, inherit);
  font-size: calc(var(--ww-cell) * 0.56);
  font-weight: 700;
  line-height: 1;
  /* The letter is in the DOM from the start so that a crossing only has to be
     agreed once — showing it is a colour change, not a content change. Which
     does mean it must be genuinely invisible until then. */
  color: transparent;
  transition: background-color 180ms ease, color 180ms ease, border-color 180ms ease;
}

/* A hole in the crossword. Kept in the grid so the rows and columns hold their
   shape without every cell carrying its own coordinates. */
.ww-cell--gap {
  border-color: transparent;
  background: none;
}

.ww-cell--shown {
  background: var(--ww-cell-shown-bg);
  border-color: var(--accent);
  color: var(--ink);
}

/* Given away rather than found. Marked, because a player looking at a finished
   board deserves to see which ones they actually got. */
.ww-cell--hinted {
  background: var(--warn-soft, var(--surface-alt));
  border-color: var(--warn, var(--rule-strong));
}

.ww-cell--pop { animation: ww-pop 260ms ease; }

@keyframes ww-pop {
  0%   { transform: scale(0.72); }
  60%  { transform: scale(1.1); }
  100% { transform: scale(1); }
}


/* ------------------------------------------------------------------ wheel */

.ww-side {
  flex: 0 1 22rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

/* The word as it is being built. Big, because it is the one thing on the
   screen the player is actually looking at while they sweep. */
.ww-staged {
  min-height: 2.4rem;
  padding: 0 0.6rem;
  border-bottom: 3px solid var(--accent);
  font-family: var(--font-head, inherit);
  font-size: 1.7rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  line-height: 2.4rem;
  white-space: nowrap;
}

/* Keeps its height and loses its rule, so nothing below it moves as letters
   come and go. */
.ww-staged--empty { border-bottom-color: var(--rule); }

.ww-wrong  { animation: ww-shake 320ms ease; color: var(--danger); }
.ww-bonus  { animation: ww-pop 300ms ease;  color: var(--ok); }
.ww-again  { animation: ww-pop 300ms ease;  color: var(--ink-muted); }

@keyframes ww-shake {
  0%, 100% { transform: translateX(0); }
  20%      { transform: translateX(-7px); }
  45%      { transform: translateX(6px); }
  70%      { transform: translateX(-4px); }
}

.ww-wheel {
  position: relative;
  width: min(21rem, 76vw);
  aspect-ratio: 1;
  border-radius: 50%;
  border: 1px solid var(--rule);
  background: var(--surface);
  /* A sweep across the wheel is a word, never a scroll. */
  touch-action: none;
  /* Half a word's worth of letters looks like a selection to a browser, and a
     blue highlight dragged across the wheel is both ugly and confusing. */
  user-select: none;
  -webkit-user-select: none;
}

/* The trail. Its COLOUR is read back by wheel.js through getComputedStyle, and
   it is set here as `color` rather than as a custom property on purpose:
   `color` computes to a real rgb() the canvas can use, where a custom property
   comes back to JavaScript as its literal token stream. That is the trap
   looseEnds/board.js documents at length, sidestepped rather than worked
   around. */
.ww-wheel__trail {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  color: var(--accent);
  opacity: 0.55;
}

.ww-letter {
  position: absolute;
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
  width: 3.4rem;
  height: 3.4rem;
  border: 2px solid var(--rule-strong);
  border-radius: 50%;
  background: var(--surface-alt);
  color: var(--ink);
  font-family: var(--font-head, inherit);
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  transition: background-color 120ms ease, color 120ms ease,
              border-color 120ms ease, transform 120ms ease;
}

.ww-letter:hover { border-color: var(--accent); }

.ww-letter--picked {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
  transform: translate(-50%, -50%) scale(1.12);
}

.ww-letter:focus-visible {
  outline: 3px solid var(--focus-ring, var(--accent));
  outline-offset: 2px;
}

/* One line saying what just happened. It is the only feedback a word gets, so
   it holds its height whether or not it has anything in it — a line that
   appears and disappears drags the wheel up and down the screen under the
   player's finger. */
.ww-status {
  min-height: 1.6rem;
  margin: 0;
  color: var(--ink-muted);
  text-align: center;
  text-wrap: balance;
}


/* The word being built, with Clear on its left and Try it on its right: the
   two buttons that belong to it, for anybody tapping letters one at a time. */
.ww-entry {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
}

.ww-entry .ww-staged {
  min-width: 4.5rem;
  text-align: center;
}

.ww-entry__btn {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 2.75rem;
  padding: 0 0.95rem;
  border: 1px solid var(--rule-strong);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 0.95rem;
  font-weight: 600;
  cursor: pointer;
  touch-action: manipulation;
}

.ww-entry__btn:hover:not(:disabled) { border-color: var(--accent); }

.ww-entry__btn--go:not(:disabled) {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}

.ww-entry__btn:disabled {
  opacity: 0.45;
  cursor: default;
}


/* ---------------------------------------------------------------- dialogs */

.ww-dialog {
  width: min(32rem, calc(100vw - 32px));
  padding: 0 18px 18px;
  border: 1px solid var(--rule-strong);
  border-radius: 12px;
  background: var(--raised, var(--surface));
  color: var(--ink);
}

.ww-dialog::backdrop { background: var(--backdrop, rgba(0, 0, 0, 0.55)); }

.ww-dialog__head {
  display: flex;
  align-items: center;
  gap: 12px;
  position: sticky;
  top: 0;
  padding: 14px 0 10px;
  background: inherit;
  border-bottom: 1px solid var(--rule);
}

.ww-dialog__head h2 { flex: 1; margin: 0; font-size: 1.25rem; }

.ww-dialog__head button {
  min-width: 2.4rem;
  min-height: 2.4rem;
  border: 1px solid var(--rule-strong);
  border-radius: 8px;
  background: var(--button-bg, var(--surface));
  color: inherit;
  font-size: 1.2rem;
  cursor: pointer;
}

.ww-dialog__title { margin: 16px 0 0; font-size: 1.25rem; }

.ww-dialog__note { margin: 14px 0 0; color: var(--ink-muted); }

.ww-dialog__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 18px;
}

.ww-dialog__actions button {
  flex: 1 1 8rem;
  min-height: 2.8rem;
  padding: 0 0.9rem;
  border: 1px solid var(--rule-strong);
  border-radius: 8px;
  background: var(--button-bg, var(--surface));
  color: var(--button-ink, var(--ink));
  font: inherit;
  cursor: pointer;
}

.ww-dialog__actions button:hover { background: var(--accent-soft); }

.stats-body h3 { margin: 18px 0 0; font-size: 1.05rem; }

.stats-list {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0;
  margin: 12px 0 0;
}

.stats-list dt {
  padding: 7px 0;
  border-bottom: 1px solid var(--rule);
  color: var(--ink-muted);
}

.stats-list dd {
  margin: 0;
  padding: 7px 0;
  border-bottom: 1px solid var(--rule);
  text-align: right;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* Bonus words, widest column that fits. There can be eighty of them on a seven
   letter wheel and they are all short, so a single list would be a very long
   thin thing to scroll. */
.ww-bonus-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(6rem, 1fr));
  gap: 4px 10px;
  margin: 14px 0 0;
  padding: 0;
  list-style: none;
  max-height: 55vh;
  overflow-y: auto;
}

.ww-bonus-list li {
  padding: 4px 0;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.06em;
}


/* How to play: the one dialog that is mostly words. */
.ww-rules { margin: 4px 0 0; }

.ww-rules h3 {
  margin: 16px 0 4px;
  font-size: 1rem;
  font-family: 'Trebuchet MS', 'Segoe UI', sans-serif;
  color: var(--accent);
}

.ww-rules p { margin: 0 0 6px; line-height: 1.5; }
.ww-rules ul { margin: 0 0 6px; padding-left: 1.2rem; }
.ww-rules li { margin: 0 0 4px; line-height: 1.45; }


/* ------------------------------------------------------------ narrow screens */

@media (max-width: 52rem) {
  .ww-shell { padding: 8px 8px 16px; }

  /* Stacked, so the grid has the whole width to itself and can use it. The
     height term still caps it, which is what stops a tall board pushing the
     wheel off the bottom of a phone. */
  .ww-grid {
    --ww-cell: clamp(1.3rem,
                     min(calc(88vw / var(--ww-cols)), calc(38vh / var(--ww-rows))),
                     2.9rem);
  }

  .ww-letter {
    width: 3rem;
    height: 3rem;
    font-size: 1.35rem;
  }

  .ww-readout__tag { margin-left: 0; }
}


/* ======================================================================
   HANDHELD MODE

   css/games/handheld.css lays the shell out: the numbers along the top
   (.hh-top), the puzzle with its dock under it (.hh-main), and the first
   screen over the lot. These are Word Wheel's own parts of it.
   ====================================================================== */

/* The puzzle's box: what the first screen covers, and what scrolls if a short
   window cannot hold the crossword and the wheel together. */
.ww-stage {
  position: relative;
  flex: 1;
  min-height: 0;
  display: flex;
  overflow-y: auto;
}

/* Centred top to bottom when there is room, and from the top when there is
   not: an auto margin in a scrolling box does both. */
.ww-play {
  flex: 1;
  margin: auto 0;
}

.hh-app .ww-readout { justify-content: center; }

/* Each number with its label, as one piece. On a phone handheld.css stands
   the label over the number (.ar-readout__item), which needs a flex box to
   stand it in. */
.ww-readout .ar-readout__item {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
}

/* The crossword and the wheel as a pair in the middle. The crossword's half
   used to grow into the spare width, which left the wheel out at the far
   side with a lake of empty page between them. */
.hh-app .ww-board { flex: 0 1 auto; }
.hh-app .ww-play { column-gap: 4rem; }

/* A phone, which is held upright for this (handheld.js asks): the puzzle
   number is in Settings rather than the line of numbers, the wheel is sized
   by the screen's height as well as its width so the crossword, the wheel
   and the dock all fit, and Clear and Try it are their icons alone. */
@media (pointer: coarse) and (max-width: 720px) {
  .hh-app .ww-readout__tag { display: none; }

  .hh-app .ww-play { gap: 8px; }

  .hh-app .ww-side { gap: 6px; }

  .hh-app .ww-wheel { width: min(76vw, 30dvh); }

  /* A third of the height for the crossword and a third for the wheel, which
     leaves the rest for the numbers, the word, the line under the wheel and
     the dock -- on an iPhone SE as well as on a big phone. */
  .hh-app .ww-grid {
    --ww-cell: clamp(1.3rem,
                     min(calc(88vw / var(--ww-cols)), calc(33dvh / var(--ww-rows))),
                     2.9rem);
  }

  .hh-app .ww-staged { font-size: 1.5rem; }

  .ww-entry__btn {
    justify-content: center;
    width: 2.9rem;
    min-height: 2.9rem;
    padding: 0;
    font-size: 1.15rem;
  }

  .ww-entry__btn span {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}


@media (prefers-reduced-motion: reduce) {
  .ww-cell,
  .ww-letter { transition: none; }

  .ww-cell--pop,
  .ww-wrong,
  .ww-bonus,
  .ww-again { animation: none; }
}
