/* =========================================================================
   开心数独 — layout: everything fits on ONE screen, no page scroll.

   Portrait  : one column  head / controls / message / board (1fr) / pad / actions
   Landscape : (aspect >= 5:4) two columns, board on the left filling the height,
               a side panel on the right with everything else.
   The board is a square = min(width, height) of its stage; digits scale with the
   board through container query units (cqw), so they follow the cell size.
   ========================================================================= */

:root {
  /* page */
  --bg-1: #e6f2ff;
  --bg-2: #f3ecff;
  --bg-3: #fff1e2;
  --surface: #ffffff;
  --surface-soft: #f3f6ff;

  /* ink */
  --ink: #26325f;
  --ink-soft: #5b6896;
  --muted: #8a95bb;

  /* brand colours */
  --accent: #4f7cff;
  --accent-dark: #3559d6;
  --accent-soft: #e1e9ff;
  --on-accent: #ffffff;
  --coral: #ff6b8b;
  --coral-soft: #ffe2e9;
  --mint: #2fc79a;
  --mint-dark: #14946f;
  --mint-soft: #d8f6ea;
  --sun: #ffb938;
  --sun-dark: #e8960c;
  --sun-soft: #fff0c4;
  --violet: #8a63f2;

  /* board */
  --line: #d3dcf2;          /* thin cell lines */
  --line-strong: #bccaee;   /* control borders */
  --box-line: #3f4e8f;      /* thick 宫 lines and board frame */
  --cell: #ffffff;
  --given-bg: #eaeffc;
  --given-ink: #26325f;     /* puzzle digits: dark, heavy */
  --user-ink: #3559d6;      /* digits the child typed: bright blue */
  --peer: #f1f5ff;          /* same row / column / box as selection */
  --same: #cddaff;          /* same digit as selection */
  --selected: #ffe08a;
  --conflict-bg: #ffe0e6;
  --conflict-ink: #d63a5a;
  --hint-bg: #d8f6ea;

  /* shape + depth */
  --radius: 16px;
  --radius-sm: 12px;
  --shadow: 0 4px 12px rgba(38, 50, 95, 0.12);
  --shadow-sm: 0 2px 6px rgba(38, 50, 95, 0.1);
  --shadow-board: 0 10px 28px rgba(38, 50, 95, 0.2);
  --shadow-inset: inset 0 2px 7px rgba(38, 50, 95, 0.4);
  --shadow-logo: drop-shadow(0 2px 4px rgba(38, 50, 95, 0.25));
  --bevel: 0 3px 0 var(--line-strong);

  /* responsive sizing helpers */
  --gap: clamp(6px, 1.3vh, 12px);
  --gap: clamp(6px, 1.3dvh, 12px);
  --key-h: clamp(44px, 7.2vh, 62px);
  --key-h: clamp(44px, 7.2dvh, 62px);
  --box-w: 2px;
  --panel-w: clamp(340px, calc(100vw - 100vh), 460px);
  --panel-w: clamp(340px, calc(100vw - 100dvh), 460px);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  overflow: hidden;
  overscroll-behavior: none;
  background-color: var(--bg-1);
  color: var(--ink);
  font-family: "PingFang SC", "Microsoft YaHei", "Segoe UI", system-ui, sans-serif;
  -webkit-tap-highlight-color: transparent;
  -webkit-text-size-adjust: 100%;
  touch-action: manipulation;
  -webkit-user-select: none;
  user-select: none;
}

body {
  background-image:
    radial-gradient(circle at 12% 8%, var(--bg-3) 0, transparent 38%),
    radial-gradient(circle at 92% 92%, var(--bg-2) 0, transparent 45%),
    linear-gradient(165deg, var(--bg-1), var(--bg-2));
  background-attachment: fixed;
}

button, select { font-family: inherit; touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
button { -webkit-user-select: none; user-select: none; }

/* ------------------------------------------------------------- icons --- */
.ico { width: 1.25em; height: 1.25em; display: block; flex: none; }
[data-icon], .btn-ico, .pill-ico, .logo, .msg-ico { display: inline-flex; align-items: center; justify-content: center; }

/* ------------------------------------------------------------ layout --- */
.app {
  max-width: 760px;
  height: 100vh;
  height: 100dvh;
  margin: 0 auto;
  padding:
    max(8px, env(safe-area-inset-top))
    max(10px, env(safe-area-inset-right))
    max(8px, env(safe-area-inset-bottom))
    max(10px, env(safe-area-inset-left));
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto auto auto minmax(0, 1fr) auto auto;
  grid-template-areas: "head" "ctrl" "msg" "stage" "pad" "act";
  gap: var(--gap);
}

/* On *.netlify.app the free-plan badge (an iframe up to 64px tall, fixed bottom-right) would cover
   the undo/redo buttons on short phones; keep that strip empty instead of hiding the badge. */
.has-host-badge .app { padding-bottom: max(64px, calc(env(safe-area-inset-bottom) + 56px)); }
/* Landscape: the control panel has no height to spare, so mirror the columns (panel left, board right)
   and let the board's stage keep the strip clear; rtl only flips the grid, children stay ltr. */
@media (min-aspect-ratio: 5/4) {
  .has-host-badge .app { direction: rtl; padding-bottom: max(8px, env(safe-area-inset-bottom)); }
  .has-host-badge .app > * { direction: ltr; }
  .has-host-badge .stage { padding-bottom: 56px; }
}

.topbar   { grid-area: head; }
.controls { grid-area: ctrl; }
.msgbar   { grid-area: msg; }
.stage    { grid-area: stage; }
.numpad   { grid-area: pad; }
.actions  { grid-area: act; }
.foot     { grid-area: foot; display: none; }

/* tall portrait screens have room for the hint line */
@media (max-aspect-ratio: 5/4) and (min-height: 800px) {
  .app {
    grid-template-rows: auto auto auto minmax(0, 1fr) auto auto auto;
    grid-template-areas: "head" "ctrl" "msg" "stage" "pad" "act" "foot";
  }
  .foot { display: block; }
}

/* landscape: board left, side panel right */
@media (min-aspect-ratio: 5/4) {
  .app {
    max-width: none;
    grid-template-columns: minmax(0, 1fr) var(--panel-w);
    grid-template-rows: minmax(0, 1fr) auto auto auto auto auto minmax(0, 1fr);
    grid-template-areas:
      "stage ."
      "stage head"
      "stage ctrl"
      "stage msg"
      "stage pad"
      "stage act"
      "stage .";
    column-gap: clamp(10px, 2vw, 24px);
  }
}
@media (min-aspect-ratio: 5/4) and (min-height: 700px) {
  .app {
    grid-template-rows: minmax(0, 1fr) auto auto auto auto auto auto minmax(0, 1fr);
    grid-template-areas:
      "stage ."
      "stage head"
      "stage ctrl"
      "stage msg"
      "stage pad"
      "stage act"
      "stage foot"
      "stage .";
  }
  .foot { display: block; }
}

/* ----------------------------------------------------------- top bar --- */
.topbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 6px 10px;
  min-height: 44px;
}

.brand { display: flex; align-items: center; gap: 8px; min-width: 0; }
.logo { width: 34px; height: 34px; flex: none; filter: var(--shadow-logo); }
.logo .ico { width: 100%; height: 100%; }

.brand h1 {
  margin: 0;
  font-size: 21px;
  font-weight: 900;
  letter-spacing: 1px;
  white-space: nowrap;
  background: linear-gradient(90deg, var(--accent-dark), var(--violet) 60%, var(--coral));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.stats { display: flex; align-items: center; gap: 6px; }

.pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 36px;
  padding: 0 10px;
  border-radius: var(--radius-sm);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  font-size: 15px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.pill-ico { width: 18px; height: 18px; }
.pill-ico .ico { width: 100%; height: 100%; }
.timer-ico { color: var(--accent); }
.trophy-ico { color: var(--sun-dark); }

.best { display: inline-flex; align-items: center; gap: 4px; }
.best-stars { display: inline-flex; }
.best-stars .ico { width: 13px; height: 13px; }
.best-time { color: var(--ink-soft); }

.ico-star.on { color: var(--sun); }
.ico-star-o.off { color: var(--muted); }

.iconbtn {
  width: 44px;
  height: 44px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--accent-dark);
  background: var(--surface);
  border: 2px solid var(--line-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
}
.iconbtn .ico { width: 24px; height: 24px; }
.iconbtn[aria-pressed="true"] { color: var(--muted); background: var(--surface-soft); }
.iconbtn:active { transform: translateY(2px); }

/* ---------------------------------------------------------- controls --- */
.controls {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) auto;
  gap: 8px;
}

.sel { position: relative; display: block; min-width: 0; }
.sel::after {
  content: "";
  position: absolute;
  right: 13px;
  top: 50%;
  width: 8px;
  height: 8px;
  border-right: 3px solid var(--accent);
  border-bottom: 3px solid var(--accent);
  transform: translateY(-75%) rotate(45deg);
  border-radius: 1px;
  pointer-events: none;
}

select {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 44px;
  padding: 0 30px 0 12px;
  font-size: 16px;
  font-weight: 800;
  color: var(--ink);
  background: var(--surface);
  border: 2px solid var(--line-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  text-overflow: ellipsis;
  -webkit-user-select: auto;
  user-select: auto;
}
select:focus-visible { outline: 3px solid var(--accent-soft); border-color: var(--accent); }

/* ----------------------------------------------------------- buttons --- */
.btn {
  min-height: 44px;
  min-width: 44px;
  padding: 0 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font-size: 16px;
  font-weight: 800;
  color: var(--ink);
  background: var(--surface);
  border: none;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow), var(--bevel);
  cursor: pointer;
  transition: transform 0.08s ease, background 0.15s ease;
}
.btn:active { transform: translateY(2px); }
.btn:disabled { opacity: 0.4; cursor: default; box-shadow: none; }
.btn:disabled:active { transform: none; }
.btn-ico { width: 22px; height: 22px; }
.btn-ico .ico { width: 100%; height: 100%; }
.hint-ico { color: var(--sun-dark); }

.btn.primary {
  color: var(--on-accent);
  background: linear-gradient(180deg, var(--accent), var(--accent-dark));
  box-shadow: var(--shadow), 0 3px 0 var(--accent-dark);
}
.btn.primary:active { transform: translateY(2px); }

/* pencil toggle lit up while active */
.btn.toggle.active {
  color: var(--on-accent);
  background: linear-gradient(180deg, var(--violet), var(--accent-dark));
  box-shadow: var(--shadow-inset);
}

/* very narrow phones: new-game becomes icon-only */
@media (max-width: 349px) {
  #new-game .btn-text { display: none; }
  #new-game { padding: 0; width: 44px; }
}
/* the title only when there is room next to timer, best and mute */
@media (max-width: 459px) { .brand h1 { display: none; } }
@media (max-width: 379px) {
  .pill { padding: 0 8px; gap: 4px; }
  .stats { gap: 5px; }
}
@media (max-width: 349px) { .logo { display: none; } .trophy-ico { display: none; } }
@media (min-aspect-ratio: 5/4) and (max-width: 1150px) { .brand h1 { display: none; } }

/* ----------------------------------------------------------- message --- */
/* msgbar = hint line + combo chip (left) + progress count (right) + progress bar (bottom edge) */
.msgbar {
  position: relative;
  display: flex;
  align-items: center;
  padding: 2px 50px 9px;
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink-soft);
  box-shadow: var(--shadow-sm);
  font-size: clamp(13px, 3.8vw, 17px);
  transition: background 0.2s ease;
}
.msgbar.win { background: var(--mint-soft); color: var(--mint-dark); }

.message {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 2px 6px;
  min-height: 2.5em;
  line-height: 1.3;
  font-weight: 800;
  text-align: center;
}
.message .msg-ico { width: 1.4em; height: 1.4em; color: var(--accent); }
.message .msg-ico .ico { width: 100%; height: 100%; }
.message .msg-stars { display: inline-flex; }
.message .msg-stars .ico { width: 1.3em; height: 1.3em; }
.message.win .msg-ico { color: var(--sun-dark); }

.prog {
  position: absolute;
  right: 9px;
  top: calc(50% - 3px);
  transform: translateY(-50%);
  font-size: 12px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
  white-space: nowrap;
}
.msgbar.win .prog { color: var(--mint-dark); }

.prog-bar {
  position: absolute;
  left: 10px;
  right: 10px;
  bottom: 4px;
  height: 4px;
  border-radius: 2px;
  background: var(--accent-soft);
  overflow: hidden;
}
.prog-bar i {
  display: block;
  height: 100%;
  width: var(--p, 0%);
  border-radius: 2px;
  background: linear-gradient(90deg, var(--mint), var(--accent));
  transition: width 0.35s ease;
}
.msgbar.win .prog-bar { background: var(--surface); }

/* combo chip: two stacked lines so it stays narrow */
.combo {
  position: absolute;
  left: 7px;
  top: calc(50% - 3px);
  transform: translateY(-50%);
  min-width: 38px;
  padding: 2px 6px 3px;
  display: flex;
  flex-direction: column;
  align-items: center;
  line-height: 1.05;
  border-radius: 10px;
  background: var(--sun-soft);
  color: var(--sun-dark);
  font-weight: 900;
}
.combo[hidden] { display: none; }
.combo small { font-size: 10px; font-weight: 800; }
.combo b { font-size: 15px; font-variant-numeric: tabular-nums; }
.combo.m5 { background: var(--sun); color: var(--ink); }
.combo.m10 { background: linear-gradient(135deg, var(--coral), var(--violet)); color: var(--on-accent); }
.combo.bump { animation: bump 0.4s ease; }

@keyframes bump {
  0% { transform: translateY(-50%) scale(0.7); }
  55% { transform: translateY(-50%) scale(1.25); }
  100% { transform: translateY(-50%) scale(1); }
}

/* ------------------------------------------------------------- board --- */
.stage {
  min-height: 0;
  min-width: 0;
  container-type: size;
  display: grid;
  place-items: center;
}

.board {
  --n: 9;
  --br: 3;
  --bc: 3;
  --bw: var(--box-w);
  position: relative;
  display: grid;
  grid-template-columns: repeat(var(--n), minmax(0, 1fr));
  grid-template-rows: repeat(var(--n), minmax(0, 1fr));
  width: min(94vw, 60vh);                 /* fallback when container units are missing */
  width: min(100cqw, 100cqh);             /* a square: the biggest that fits the stage */
  aspect-ratio: 1 / 1;
  container-type: inline-size;            /* cells size their digits from the board's width */
  background: var(--cell);
  border: 3px solid var(--box-line);
  border-radius: 14px;
  overflow: hidden;
  box-shadow: var(--shadow-board);
  touch-action: manipulation;
}

/* thick 宫 lines: one overlay, repeating every (box width / board width) */
.board::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 2;
  --pw: calc(100% * var(--bc) / var(--n));
  --ph: calc(100% * var(--br) / var(--n));
  background:
    repeating-linear-gradient(to right,
      transparent 0, transparent calc(var(--pw) - var(--bw)),
      var(--box-line) calc(var(--pw) - var(--bw)), var(--box-line) var(--pw)),
    repeating-linear-gradient(to bottom,
      transparent 0, transparent calc(var(--ph) - var(--bw)),
      var(--box-line) calc(var(--ph) - var(--bw)), var(--box-line) var(--ph));
}

.cell {
  position: relative;
  min-width: 0;
  min-height: 0;
  padding: 0;
  margin: 0;
  border: 0;
  border-radius: 0;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--cell);
  isolation: isolate;                            /* ::before wave sits above the fill, below the digit */
  box-shadow: inset -1px -1px 0 var(--line);   /* thin right + bottom lines */
  font-size: clamp(14px, 5.2vmin, 28px);        /* fallback */
  font-size: calc(100cqw / var(--n) * 0.6);     /* follows the cell size */
  font-weight: 700;
  line-height: 1;
  color: var(--user-ink);                        /* digits typed by the child */
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
}

/* state colours, later rules win: given < peer < same < hinted < conflict < selected */
.cell.given { background: var(--given-bg); color: var(--given-ink); font-weight: 900; }
.cell.peer { background: var(--peer); }
.cell.same { background: var(--same); }
.cell.hinted { background: var(--hint-bg); color: var(--mint-dark); }
.cell.conflict { background: var(--conflict-bg); color: var(--conflict-ink); }
.cell.selected {
  background: var(--selected);
  outline: 3px solid var(--sun-dark);
  outline-offset: -3px;
  z-index: 1;
}

/* pencil-mode candidate marks as a mini grid inside an empty cell */
.cell .notes {
  display: grid;
  grid-template-columns: repeat(var(--nc, 3), minmax(0, 1fr));
  width: 100%;
  height: 100%;
  padding: 1px;
  font-size: 8px;                                               /* fallback */
  font-size: max(7px, calc(100cqw / var(--n) / var(--nc, 3) * 1.05));
  font-weight: 700;
  line-height: 1;
  color: var(--ink-soft);
}
.cell .notes span { display: flex; align-items: center; justify-content: center; }

@keyframes pop {
  0% { transform: scale(0.55); }
  60% { transform: scale(1.18); }
  100% { transform: scale(1); }
}
.cell.pop { animation: pop 0.25s ease; }

@keyframes shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-3px); }
  40% { transform: translateX(3px); }
  60% { transform: translateX(-2px); }
  80% { transform: translateX(2px); }
}
.cell.shake { animation: shake 0.3s ease; }

@media (min-width: 700px) and (min-height: 700px) { :root { --box-w: 3px; } }

/* ------------------------------------------------------------ numpad --- */
.numpad {
  display: grid;
  grid-template-columns: repeat(var(--cols, 5), minmax(0, 1fr));
  gap: 5px;
  width: 100%;
}

.num {
  height: var(--key-h);
  min-width: 44px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: clamp(22px, calc(var(--key-h) * 0.52), 32px);
  font-weight: 900;
  color: var(--accent-dark);
  background: var(--surface);
  border: 2px solid var(--line-strong);
  border-radius: 14px;
  box-shadow: var(--shadow-sm), var(--bevel);
  cursor: pointer;
}
.num:active { transform: translateY(2px); box-shadow: var(--shadow-sm); background: var(--accent-soft); }
.num .ico { width: 1.05em; height: 1.05em; }
.num.erase { color: var(--coral); background: var(--coral-soft); border-color: var(--coral-soft); }
.num.erase.wide { grid-column: 1 / -1; }

/* ----------------------------------------------------------- actions --- */
.actions {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 6px;
}
.actions .btn { height: clamp(44px, 6.4vh, 54px); height: clamp(44px, 6.4dvh, 54px); padding: 0 4px; }

/* -------------------------------------------------------------- foot --- */
.foot {
  text-align: center;
  font-size: 13px;
  line-height: 1.4;
  color: var(--ink-soft);
  padding: 0 6px;
}

/* =========================================================================
   P2: rewards. good fill, unit sweep, overlays, toast, badges
   ========================================================================= */
:root {
  --scrim: rgba(38, 50, 95, 0.45);
  --shadow-sheet: 0 18px 50px rgba(38, 50, 95, 0.35);
  --shadow-badge: rgba(38, 50, 95, 0.28);
}

/* a digit that matches the answer: bigger bounce plus a soft mint ring */
@keyframes good {
  0% { transform: scale(0.55); box-shadow: inset 0 0 0 0 var(--mint); }
  55% { transform: scale(1.22); box-shadow: inset 0 0 0 4px var(--mint); }
  100% { transform: scale(1); box-shadow: inset -1px -1px 0 var(--line); }
}
.cell.good { animation: good 0.42s ease; z-index: 1; }

/* a finished row / column / box: a coloured band sweeps over its cells */
.cell.wave::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0;
  background: linear-gradient(90deg, transparent, var(--wc, var(--sun)) 45%, var(--wc, var(--sun)) 55%, transparent);
  animation: sweep-x 0.75s ease-out var(--wd, 0s) both;
}
.cell.wave-v::before { background: linear-gradient(180deg, transparent, var(--wc, var(--sun)) 45%, var(--wc, var(--sun)) 55%, transparent); animation-name: sweep-y; }
.cell.wave-b::before { background: radial-gradient(circle, var(--wc, var(--sun)) 35%, transparent 75%); animation-name: sweep-b; }

@keyframes sweep-x {
  0% { opacity: 0; transform: translateX(-100%); }
  35% { opacity: 0.9; transform: translateX(0); }
  100% { opacity: 0; transform: translateX(100%); }
}
@keyframes sweep-y {
  0% { opacity: 0; transform: translateY(-100%); }
  35% { opacity: 0.9; transform: translateY(0); }
  100% { opacity: 0; transform: translateY(100%); }
}
@keyframes sweep-b {
  0% { opacity: 0; transform: scale(0.4); }
  40% { opacity: 0.9; transform: scale(1.1); }
  100% { opacity: 0; transform: scale(1.5); }
}

/* canvas confetti */
.confetti-canvas {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  z-index: 70;
  pointer-events: none;
}

/* ---------------------------------------------------------- overlays --- */
.overlay {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: center;
  padding:
    max(12px, env(safe-area-inset-top))
    max(12px, env(safe-area-inset-right))
    max(12px, env(safe-area-inset-bottom))
    max(12px, env(safe-area-inset-left));
  background: var(--scrim);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  animation: fade-in 0.2s ease;
}
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

.sheet {
  position: relative;
  width: 100%;
  max-width: 520px;
  max-height: calc(100vh - 24px);
  max-height: calc(100dvh - 24px);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 16px;
  border-radius: 22px;
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow-sheet);
  animation: sheet-in 0.28s cubic-bezier(0.2, 0.9, 0.3, 1.2);
}
@keyframes sheet-in { from { opacity: 0; transform: translateY(14px) scale(0.96); } to { opacity: 1; transform: none; } }

.sheet h2 { margin: 0; font-size: 22px; font-weight: 900; }
.sheet-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 10px; }

.sheet-close {
  width: 44px;
  height: 44px;
  padding: 0;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-soft);
  background: var(--surface-soft);
  border: 0;
  border-radius: 14px;
  cursor: pointer;
}
.sheet-close .ico { width: 22px; height: 22px; }
.sheet-close.abs { position: absolute; top: 8px; right: 8px; }
.sheet-close:active { transform: translateY(2px); }

/* badge wall */
.wall-sum { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.chip {
  flex: 1 1 0;
  min-width: 90px;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 8px 6px;
  border-radius: 14px;
  background: var(--accent-soft);
  color: var(--ink-soft);
  font-size: 12px;
  font-weight: 800;
}
.chip b { font-size: 22px; font-weight: 900; color: var(--accent-dark); font-variant-numeric: tabular-nums; }

.badge-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px 8px;
}
.badge { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 4px; }
.badge-art { display: inline-flex; width: 64px; height: 64px; flex: none; }
.badge-art .ico { width: 100%; height: 100%; filter: drop-shadow(0 3px 4px var(--shadow-badge)); }
.badge-name { font-size: 14px; font-weight: 900; line-height: 1.2; }
.badge-desc { font-size: 11.5px; line-height: 1.35; font-weight: 700; color: var(--ink-soft); }
.badge.locked .badge-art .ico { filter: grayscale(1) brightness(1.12) opacity(0.5); }
.badge.locked .badge-name { color: var(--muted); }
.badge.locked .badge-desc { color: var(--muted); }

@media (min-width: 520px) { .badge-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* finish card */
.settle { text-align: center; padding-top: 22px; }
.settle-stars { display: flex; justify-content: center; gap: 8px; margin: 10px 0 4px; }
.settle-stars .ico { width: 52px; height: 52px; }
.settle-stars .ico-star-o { color: var(--line-strong); }
.settle-stars .ico-star.lit { animation: star-in 0.55s cubic-bezier(0.2, 1.4, 0.4, 1) calc(0.35s + var(--i, 0) * 0.33s) both; }
@keyframes star-in {
  0% { transform: scale(0.2) rotate(-40deg); color: var(--line-strong); opacity: 0.2; }
  60% { transform: scale(1.3) rotate(8deg); color: var(--sun); opacity: 1; }
  100% { transform: scale(1) rotate(0); color: var(--sun); opacity: 1; }
}
.settle-phrase { margin: 4px 0 12px; font-size: 15px; font-weight: 800; color: var(--ink-soft); }
.settle-stats { display: flex; gap: 10px; justify-content: center; }
.stat-box {
  flex: 1 1 0;
  max-width: 160px;
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto;
  column-gap: 8px;
  row-gap: 2px;
  align-items: center;
  padding: 8px 10px;
  text-align: left;
  border-radius: 14px;
  background: var(--surface-soft);
}
.stat-box .stat-ico { grid-row: 1 / 3; width: 28px; height: 28px; color: var(--accent); }
.stat-box .stat-ico .ico { width: 100%; height: 100%; }
.stat-box b { font-size: 20px; font-weight: 900; font-variant-numeric: tabular-nums; line-height: 1.1; }
.stat-box small { font-size: 12px; line-height: 1.2; font-weight: 800; color: var(--muted); }

.settle-record {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 12px;
  padding: 6px 14px;
  border-radius: 999px;
  background: var(--sun-soft);
  color: var(--sun-dark);
  font-weight: 900;
}
.settle-record .ico { width: 20px; height: 20px; }

.settle-unlocks { margin-top: 12px; padding: 10px; border-radius: 16px; background: var(--mint-soft); }
.settle-unlocks h3 { margin: 0 0 6px; font-size: 13px; font-weight: 900; color: var(--mint-dark); }
.settle-unlocks ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.settle-unlocks li { display: flex; flex-direction: column; align-items: center; gap: 2px; width: 78px; font-size: 12px; font-weight: 800; line-height: 1.2; color: var(--ink); }
.settle-unlocks .badge-art { width: 52px; height: 52px; }
.settle-unlocks li { animation: badge-pop 0.5s cubic-bezier(0.2, 1.4, 0.4, 1) 0.9s both; }
@keyframes badge-pop { from { transform: scale(0.3); opacity: 0; } to { transform: none; opacity: 1; } }

.settle-actions { display: flex; gap: 10px; margin-top: 16px; }
.settle-actions .btn { flex: 1 1 0; min-height: 48px; font-size: 16px; }
.btn.harder { color: var(--accent-dark); }

/* toast */
.toast-root {
  position: fixed;
  top: max(8px, env(safe-area-inset-top));
  left: 0;
  right: 0;
  z-index: 80;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  pointer-events: none;
}
.toast {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 16px 6px 8px;
  border-radius: 999px;
  background: var(--surface);
  box-shadow: var(--shadow-sheet);
  border: 2px solid var(--sun);
  animation: toast 2s ease both;
}
.toast .badge-art { width: 36px; height: 36px; }
.toast-text { display: flex; flex-direction: column; line-height: 1.15; }
.toast-text small { font-size: 11px; font-weight: 800; color: var(--sun-dark); }
.toast-text b { font-size: 15px; font-weight: 900; color: var(--ink); }
@keyframes toast {
  0% { opacity: 0; transform: translateY(-24px) scale(0.9); }
  12% { opacity: 1; transform: none; }
  85% { opacity: 1; transform: none; }
  100% { opacity: 0; transform: translateY(-10px); }
}

@media (max-height: 420px) {
  .sheet { padding: 12px; }
  .settle-stars .ico { width: 40px; height: 40px; }
}

@media (prefers-reduced-motion: reduce) {
  .cell.pop, .cell.shake, .cell.good { animation: none; }
  .cell.wave::before { animation: none; }
  .combo.bump, .overlay, .sheet, .settle-unlocks li { animation: none; }
  .settle-stars .ico-star.lit { animation: none; color: var(--sun); }
  .toast { animation: none; }
  .prog-bar i { transition: none; }
  .msgbar { transition: none; }
}
