/**
 * Sudoku — tool styles
 *
 * The layout is ported from LordRikiller/Sudoku (the 9x9 board with heavier 3x3
 * box rules, the number pad, the cell states, the placement and completion
 * animations). Every colour it used is gone: upstream carried eleven hand-built
 * themes and a pile of literal hex values, this file carries none and reads
 * everything from --fw-* tokens so frikwork's light/dark is the only theming.
 *
 * Cards, tabs, tables, buttons, meters and dialogs all come from frikwork
 * untouched. What is here is the board geometry and the seven keyframes frikwork
 * has no equivalent for — every one of which is switched off in the
 * reduced-motion block at the foot of the file, matching what frikwork already
 * does for its own.
 */

:root {
  /* Upstream's two animation accents, rebuilt from tokens. --sud-complete
     sweeps a finished row/column/box; --sud-win drives the solved-board wave. */
  --sud-complete: var(--fw-info);
  --sud-win: var(--fw-warning);
}

.sud-layout {
  display: grid;
  grid-template-columns: minmax(280px, 340px) 1fr;
  gap: var(--fw-space-lg);
  align-items: start;
}

.sud-play {
  display: flex;
  flex-direction: column;
  gap: var(--fw-space-lg);
  min-width: 0;
}

/* --- Settings --------------------------------------------------------------
   .fw-tabs--segmented is an inline-flex track that scrolls when it runs out of
   room. In a 340px sidebar the four difficulties would become a scroll strip,
   so the track is re-laid as a full-width grid and keeps its own chrome. */

.sud-seg {
  display: grid;
  grid-template-columns: repeat(var(--sud-seg-cols, 2), minmax(0, 1fr));
  overflow-x: visible;
  width: 100%;
}

.sud-seg--four { --sud-seg-cols: 4; }

/* The daily's fixed level, standing where free play has a picker.
   Weighted like a stat value (.app-stat__value's idiom) so it reads as a fact
   about today rather than a control: no border, no hover, no pointer.

   Colour is left to --fw-text on purpose. --fw-brand-text would be the obvious
   accent pick and is NOT safe for text here: it resolves to the same olive as
   --fw-success and measures 4.11:1 on a light card, under the 4.5:1 bar — the
   measurement tools/boggle/style.css already paid for. Nothing about a
   read-only level is worth a colour-contrast risk, so it takes the body token,
   which is AA in all four theme states by construction. */
.sud-level {
  margin: 0;
  padding: var(--fw-space-xs) 0;
  font-size: 1.15rem;
  font-weight: 700;
  line-height: 1.3;
  color: var(--fw-text);
}

.sud-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--fw-space-sm);
}

/* New game spans the row above the four secondary actions. */
.sud-actions > .fw-btn--block { grid-column: 1 / -1; }

.sud-keys {
  margin-top: var(--fw-space-md);
  line-height: 1.7;
}

/* --- The board ------------------------------------------------------------- */

.sud-board-wrap {
  display: flex;
  justify-content: center;
}

.sud-grid {
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  grid-template-rows: repeat(9, 1fr);
  gap: 2px;
  width: 100%;
  max-width: 34rem;
  aspect-ratio: 1;
  padding: var(--fw-space-sm);
  border: 1px solid var(--fw-border);
  border-radius: var(--fw-radius-lg);
  background: var(--fw-bg-2);
  /* Anchors the confetti overlay to the board. */
  position: relative;
}

.sud-cell {
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  box-sizing: border-box;
  min-width: 0;
  border: 1px solid var(--fw-border);
  border-radius: var(--fw-radius-sm);
  background: var(--fw-bg-card);
  color: var(--fw-text);
  font-size: clamp(0.85rem, 2.6vw, 1.35rem);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: background var(--fw-dur-fast) ease, border-color var(--fw-dur-fast) ease;
}

.sud-cell:hover { background: var(--fw-bg-hover); }

/* 3x3 box rules. Both properties can land on the same cell, and because the
   grid track fixes the cell's outer size a thicker border eats into the content
   box rather than moving anything. */
.sud-cell:nth-child(3n):not(:nth-child(9n)) {
  border-right: 3px solid var(--fw-brand-text);
}
.sud-cell:nth-child(n+19):nth-child(-n+27),
.sud-cell:nth-child(n+46):nth-child(-n+54) {
  border-bottom: 3px solid var(--fw-brand-text);
}

/* Cell states. Ordered so the strongest wins: given < related < same < hint <
   invalid < selected. */

/* Givens carry a brand tint, as upstream's --cell-highlight did, because a
   player has to be able to see at a glance which digits are theirs to change.
   The obvious token pick, --fw-bg-2, is not usable here: it resolves to the
   same #ffffff as --fw-bg-card in the light theme and to within 5/255 of it in
   the dark one, so a given and a digit you placed yourself were separated by
   nothing but font-weight. Measured in both themes, not guessed. */
.sud-cell.is-given {
  background: color-mix(in srgb, var(--fw-brand) 16%, var(--fw-bg-card));
  font-weight: 700;
  cursor: default;
}
.sud-cell.is-given:hover { background: color-mix(in srgb, var(--fw-brand) 16%, var(--fw-bg-card)); }

.sud-cell.is-row,
.sud-cell.is-col,
.sud-cell.is-box { background: var(--fw-bg-hover); }

.sud-cell.is-same {
  background: color-mix(in srgb, var(--fw-brand) 22%, transparent);
  border-color: var(--fw-brand);
}

.sud-cell.is-hint {
  background: color-mix(in srgb, var(--fw-success) 28%, transparent);
  border-color: var(--fw-success);
  animation: sud-hint-glow 1s ease-in-out;
}

.sud-cell.is-invalid {
  background: color-mix(in srgb, var(--fw-danger) 26%, transparent);
  border-color: var(--fw-danger);
  animation: sud-shake 0.5s ease-in-out;
}

.sud-cell.is-selected {
  background: var(--fw-brand);
  color: var(--fw-on-primary);
  border-color: var(--fw-brand);
}

/* The digit lives in its own span so entrance animations can target the number
   alone, never the cell, its fill or its borders. Sits above the ripple. */
.sud-num {
  display: inline-block;
  position: relative;
  z-index: 2;
}

/* --- Number pad ------------------------------------------------------------ */

.sud-pad {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--fw-space-sm);
  margin-top: var(--fw-space-lg);
}

.sud-pad__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.15rem;
  position: relative;
  min-height: 3.6rem;
  padding: var(--fw-space-sm) var(--fw-space-xs);
  border: 1px solid var(--fw-border);
  border-radius: var(--fw-radius-md);
  background: var(--fw-bg-2);
  color: var(--fw-text);
  font: inherit;
  cursor: pointer;
  transition: background var(--fw-dur-fast) ease, border-color var(--fw-dur-fast) ease;
}

.sud-pad__item:hover {
  background: var(--fw-bg-hover);
  border-color: var(--fw-brand-text);
}

.sud-pad__item.is-selected {
  background: var(--fw-brand);
  border-color: var(--fw-brand);
  color: var(--fw-on-primary);
}

/* Depleted digits stay tappable — the count is the signal, not the state. */
.sud-pad__item.is-depleted { opacity: 0.5; }

.sud-pad__num {
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1;
}

.sud-pad__count {
  font-size: 0.7rem;
  color: var(--fw-text-muted);
  line-height: 1;
}

.sud-pad__item.is-selected .sud-pad__count { color: var(--fw-on-primary); }

.sud-pad__item--erase {
  border-color: color-mix(in srgb, var(--fw-danger) 45%, var(--fw-border));
  color: var(--fw-danger);
}
.sud-pad__item--erase:hover {
  border-color: var(--fw-danger);
  background: color-mix(in srgb, var(--fw-danger) 10%, transparent);
}
.sud-pad__item--erase.is-selected {
  background: var(--fw-danger);
  border-color: var(--fw-danger);
  color: var(--fw-on-primary);
}
.sud-pad__item--erase.is-selected .sud-pad__count { color: var(--fw-on-primary); }

/* --- Status, stats, progress ---------------------------------------------- */

.sud-status {
  margin: var(--fw-space-lg) 0 0;
  padding: var(--fw-space-sm) var(--fw-space-md);
  border: 1px solid var(--fw-border);
  border-radius: var(--fw-radius-md);
  background: var(--fw-bg-2);
  color: var(--fw-text-2);
  text-align: center;
  min-height: 2.75rem;
}

.sud-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: var(--fw-space-md);
}

/* Each tile is wrapped so script.js has an id to hang off; the wrapper must not
   shrink the ccm_stat() card it holds. */
.sud-stat { display: flex; }
.sud-stat > .fw-card { flex: 1 1 auto; }

.sud-progress { margin-top: var(--fw-space-lg); }

.sud-progress__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: var(--fw-space-xs);
}

/* --- Leaderboard ---------------------------------------------------------- */

.sud-board__scope {
  margin-top: 0;
  font-weight: 600;
  color: var(--fw-brand-text);
}

.sud-board__rank { width: 3rem; color: var(--fw-text-muted); }
.sud-board__initials { font-weight: 700; letter-spacing: 0.06em; }
.sud-board__num { text-align: right; font-variant-numeric: tabular-nums; }
.sud-board__note { margin-bottom: 0; }

/* --- Dialog content ------------------------------------------------------- */

.sud-verdict {
  margin: 0 0 var(--fw-space-md);
  padding: var(--fw-space-md);
  border: 1px solid var(--fw-border);
  border-radius: var(--fw-radius-md);
  background: var(--fw-bg-2);
  line-height: 1.5;
}

/* The roastings and the surrender speech. Bordered in danger rather than
   coloured in it, so a long paragraph stays readable in both themes. */
.sud-verdict--harsh {
  border-color: color-mix(in srgb, var(--fw-danger) 55%, transparent);
  background: color-mix(in srgb, var(--fw-danger) 8%, var(--fw-bg-2));
  font-weight: 600;
}

/* 4.5rem tracks so the win dialog's four facts sit on one row inside a default
   modal body and the roast's three spread across it, rather than wrapping 3+1. */
.sud-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(4.5rem, 1fr));
  gap: var(--fw-space-sm);
  margin: 0 0 var(--fw-space-md);
  padding: var(--fw-space-md);
  border: 1px solid var(--fw-border);
  border-radius: var(--fw-radius-md);
  background: var(--fw-bg-2);
}

.sud-facts__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
  text-align: center;
}

.sud-facts dt {
  font-size: 0.8rem;
  color: var(--fw-text-muted);
}

.sud-facts dd {
  margin: 0;
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--fw-brand-text);
}

.sud-initials {
  text-transform: uppercase;
  letter-spacing: 0.3em;
  text-align: center;
  font-size: 1.4rem;
  font-weight: 700;
}

/* --- Motion ---------------------------------------------------------------
   Ported from upstream. Everything animates the digit span, the pad tile or a
   throwaway overlay — never the cell box — so the grid never shifts. */

/* 1 · New game: each given zooms into place, staggered top-to-bottom. */
@keyframes sud-drop {
  0%   { opacity: 0; transform: scale(0) rotate(-25deg); }
  100% { opacity: 1; transform: scale(1) rotate(0); }
}
.sud-num.is-drop { animation: sud-drop 0.5s var(--fw-ease-pop, cubic-bezier(0.34, 1.56, 0.64, 1)) both; }

/* 2 · Number placed: the digit pops and a ring ripples out of the cell. */
@keyframes sud-pop {
  0%   { transform: scale(0);    opacity: 0; }
  60%  { transform: scale(1.35); opacity: 1; }
  100% { transform: scale(1); }
}
.sud-num.is-pop { animation: sud-pop 0.38s var(--fw-ease-pop, cubic-bezier(0.34, 1.6, 0.6, 1)) both; }

@keyframes sud-ripple {
  0%   { transform: translate(-50%, -50%) scale(0); opacity: 0.6; }
  100% { transform: translate(-50%, -50%) scale(5); opacity: 0; }
}
.sud-ripple {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  transform: translate(-50%, -50%) scale(0);
  background: radial-gradient(circle, var(--fw-brand) 0%, transparent 70%);
  pointer-events: none;
  z-index: 1;
  animation: sud-ripple 0.55s ease-out forwards;
}

/* 3 · Row / column / box completed: a wave sweeps the group. Only the fill,
   the glow and the digit animate; the borders stay put. */
@keyframes sud-flash {
  0%   { background: var(--fw-bg-card);   box-shadow: none; }
  30%  { background: var(--sud-complete); box-shadow: 0 0 20px var(--sud-complete); }
  100% { background: var(--fw-bg-card);   box-shadow: none; }
}
.sud-cell.is-flash { animation: sud-flash 0.7s ease-out; }

@keyframes sud-flash-num {
  0%   { transform: scale(1);   color: var(--fw-text); }
  30%  { transform: scale(1.3); color: var(--fw-on-primary); }
  100% { transform: scale(1);   color: var(--fw-text); }
}
.sud-cell.is-flash .sud-num { animation: sud-flash-num 0.7s ease-out; }

/* 4 · Puzzle solved: a diagonal wave of colour rolls across the digits. */
@keyframes sud-winpop {
  0%   { transform: scale(1)    rotate(0);     color: var(--fw-text); }
  40%  { transform: scale(1.45) rotate(12deg); color: var(--sud-win); }
  70%  { transform: scale(1.45) rotate(-8deg); color: var(--sud-win); }
  100% { transform: scale(1)    rotate(0);     color: var(--fw-text); }
}
.sud-num.is-win { animation: sud-winpop 0.9s ease-out both; }

/* Confetti overlay for the win, clipped to the rounded board. */
.sud-confetti-layer {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  border-radius: var(--fw-radius-lg);
  z-index: 3;
}

@keyframes sud-confetti {
  0%   { opacity: 1; transform: translateY(-14px) rotate(0); }
  100% { opacity: 0; transform: translateY(600px) rotate(720deg); }
}
.sud-confetti {
  position: absolute;
  top: -14px;
  width: 9px;
  height: 14px;
  border-radius: 2px;
  opacity: 0;
  animation: sud-confetti linear forwards;
}
/* Six colourways, all from tokens, so the shower tracks the theme. */
.sud-confetti--1 { background: var(--fw-brand); }
.sud-confetti--2 { background: var(--fw-success); }
.sud-confetti--3 { background: var(--fw-warning); }
.sud-confetti--4 { background: var(--fw-danger); }
.sud-confetti--5 { background: var(--fw-info); }
.sud-confetti--6 { background: var(--fw-brand-text); }

/* 5 · Cell feedback: a shake for an illegal placement, a glow for a hint. */
@keyframes sud-shake {
  0%, 100% { transform: translateX(0); }
  25%      { transform: translateX(-3px); }
  75%      { transform: translateX(3px); }
}

@keyframes sud-hint-glow {
  0%   { box-shadow: 0 0 18px var(--fw-success); }
  100% { box-shadow: none; }
}

/* 6 · Number pad: a press squish, and a pop when a digit is fully used up. */
@keyframes sud-pad-tap {
  0%   { transform: scale(1); }
  40%  { transform: scale(0.86); }
  100% { transform: scale(1); }
}
.sud-pad__item.is-tapped { animation: sud-pad-tap 0.28s ease-out; }

@keyframes sud-pad-depleted {
  0%   { transform: scale(1);    opacity: 1;   box-shadow: none; }
  35%  { transform: scale(1.25); opacity: 1;   box-shadow: 0 0 20px var(--sud-complete); }
  100% { transform: scale(1);    opacity: 0.5; box-shadow: none; }
}
.sud-pad__item.is-popped {
  z-index: 2;
  animation: sud-pad-depleted 0.6s var(--fw-ease-pop, cubic-bezier(0.34, 1.56, 0.64, 1));
}

/* --- Responsive ---------------------------------------------------------- */

@media (max-width: 960px) {
  .sud-layout { grid-template-columns: 1fr; }
}

@media (max-width: 560px) {
  .sud-grid { gap: 1px; padding: var(--fw-space-xs); }
  .sud-cell { border-radius: 3px; }
  .sud-cell:nth-child(3n):not(:nth-child(9n)) { border-right-width: 2px; }
  .sud-cell:nth-child(n+19):nth-child(-n+27),
  .sud-cell:nth-child(n+46):nth-child(-n+54) { border-bottom-width: 2px; }
  .sud-pad { gap: var(--fw-space-xs); }
  .sud-pad__item { min-height: 3rem; padding: var(--fw-space-xs) 2px; }
  .sud-pad__num { font-size: 1.05rem; }
  .sud-actions { grid-template-columns: 1fr; }
  .sud-keys { display: none; }
}

/* Same contract frikwork honours for its own animations: no motion, but every
   colour state still reads. */
@media (prefers-reduced-motion: reduce) {
  .sud-cell,
  .sud-pad__item { transition: none; }

  .sud-num.is-drop,
  .sud-num.is-pop,
  .sud-num.is-win,
  .sud-cell.is-flash,
  .sud-cell.is-flash .sud-num,
  .sud-cell.is-hint,
  .sud-cell.is-invalid,
  .sud-pad__item.is-tapped,
  .sud-pad__item.is-popped { animation: none; }

  .sud-ripple,
  .sud-confetti-layer { display: none; }
}
