/* ==========================================================================
   NyonNyonNyon — design tokens
   Palette rule: warm cream base, low-saturation pastel accents.
   Nothing above ~60% saturation, nothing pure-black. Kid-friendly but calm.
   ========================================================================== */
:root {
  --bg:        #fdf6ec;
  --bg-soft:   #f7ecdd;
  --surface:   #fffdf9;
  --ink:       #4a4038;
  --ink-soft:  #8a7c6d;
  --line:      #e6d9c6;

  /* ACCENTS NOW MATCH THE COVER ART, not the old pastels. The 33 covers are
     drawn in a papercut palette (terracotta / deep teal / mustard / sage) with
     heavy ink outlines; the chrome used to be a separate, much paler language,
     so the app read as a generic UI that happened to have nice pictures glued
     on. These are the cover colours, so card and chrome belong together. */
  --c1: #3f7d74;  /* deep teal   — wordsearch */
  --c2: #4a6fa5;  /* deep blue   — block slide */
  --c3: #d9683f;  /* terracotta  — maze  (the covers' own background) */
  --c4: #c8912f;  /* mustard     — pipes */
  --c5: #8d6bb0;  /* plum        — snap */
  --c6: #6f9451;  /* olive       — shikaku */
  --c7: #c96a86;  /* rose        — atoms */
  --c8: #3f8b93;  /* sea teal    — sudoku */

  --good:  #4f8f78;
  --warn:  #c9702f;
  --star:  #e6b33c;

  /* the ink line every cover is drawn with — reused as the UI's outline */
  --ink-line: #2f2a26;

  --r-sm: 10px;
  --r-md: 16px;
  --r-lg: 22px;

  /* HARD OFFSET SHADOWS, NOT SOFT BLUR. This is the single change that makes
     the interface read as cut paper rather than as a stock SaaS card: real
     stacked paper throws a crisp displaced edge, and a big soft blur is the
     giveaway of a default component library. Blur stays only as a faint
     ambient wash underneath so nothing looks pasted on. */
  --shadow:    3px 3px 0 var(--ink-line), 0 4px 10px rgba(60,44,32,.10);
  --shadow-lg: 5px 5px 0 var(--ink-line), 0 10px 22px rgba(60,44,32,.13);
  --border:    2.5px solid var(--ink-line);

  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
}

/* SELF-HOSTED, NOT GOOGLE FONTS. This is an offline-first PWA: a webfont
   loaded from fonts.gstatic.com simply does not arrive when the child has no
   signal, and the app would silently fall back to the system font — which is
   exactly the bug this fixes. One variable file covers weights 400-900.

   Nunito is SIL Open Font License: free to self-host and ship commercially. */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 400 900;               /* variable axis, one file, all weights */
  font-display: swap;
  src: url('../assets/fonts/nunito-latin.woff2') format('woff2');
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  margin: 0; height: 100%;
  overflow: hidden;
  overscroll-behavior: none;
}

body {
  background: var(--bg);
  color: var(--ink);
  font-family: "Nunito", "Quicksand", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  font-size: 16px;
  -webkit-user-select: none; user-select: none;
  touch-action: manipulation;

  /* PAPER GRAIN, as an inline SVG rather than an image file: it costs no extra
     request, cannot fail to load offline, and scales to any screen. Two soft
     colour washes sit under it so the cream is never a flat digital fill —
     flatness is the other half of why the old chrome looked machine-made. */
  background-image:
    radial-gradient(circle at 15% 0%, rgba(217,104,63,.07), transparent 45%),
    radial-gradient(circle at 85% 12%, rgba(63,125,116,.06), transparent 42%),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.05'/%3E%3C/svg%3E");
  background-attachment: fixed;
}

/* ---------- Bomb Detector -------------------------------------------------
   Number cells are calm brand tiles; thick ink borders communicate regions.
   The player should never have to infer an area boundary from colour alone. */
.bd-rules {
  width: min(100%, 420px);
  padding: 9px 13px;
  border: 1.5px solid color-mix(in srgb, var(--ink-line) 16%, transparent);
  border-radius: 15px;
  background: color-mix(in srgb, var(--surface) 90%, transparent);
  text-align: center;
  font-size: 13px;
  font-weight: 750;
}
.bd-rules b { color: var(--c1); font-weight: 900; }
.bd-region-card {
  width: min(100%, 420px);
  padding: 8px 10px 10px;
  border: 1.5px solid color-mix(in srgb, var(--ink-line) 16%, transparent);
  border-radius: 16px;
  background: color-mix(in srgb, var(--surface) 92%, transparent);
}
.bd-region-card > span {
  display: block;
  margin-bottom: 6px;
  color: var(--ink-soft);
  text-align: center;
  font-size: 11px;
  font-weight: 900;
}
.bd-region-guide {
  display: grid;
  grid-template-columns: repeat(var(--bd-guide-cols), 1fr);
  gap: 4px;
}
.bd-target {
  display: grid;
  place-items: center;
  min-height: 25px;
  border: 1px solid color-mix(in srgb, var(--ink-line) 18%, transparent);
  border-radius: 7px;
  color: var(--ink);
  font-size: 11px;
  font-style: normal;
  font-weight: 900;
}
.bd-target-1 { --bd-tint: #dcebe5; }
.bd-target-2 { --bd-tint: #cfe2da; }
.bd-target-3 { --bd-tint: #f6eab7; }
.bd-target-4 { --bd-tint: #f8d6e2; }
.bd-target-5 { --bd-tint: #e6dcf2; }
.bd-region-guide .bd-target { background: var(--bd-tint); }
.bd-hud { min-width: 82px; }
.bd-board-shell {
  width: min(100%, 420px);
  padding: 7px;
  border: 1.5px solid color-mix(in srgb, var(--ink-line) 20%, transparent);
  border-radius: 20px;
  background: color-mix(in srgb, var(--surface) 94%, transparent);
  box-shadow: var(--shadow-lg);
}
.bd-board {
  display: grid;
  grid-template-columns: repeat(var(--bd-size), 1fr);
  overflow: hidden;
  border: 3px solid var(--ink-line);
  border-radius: 12px;
  background: var(--ink-line);
}
.bd-cell {
  position: relative;
  display: grid;
  place-items: center;
  min-width: 0;
  aspect-ratio: 1;
  padding: 0;
  border: 0;
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background: color-mix(in srgb, var(--bd-tint) 14%, white);
  color: var(--ink);
  font: inherit;
  font-size: clamp(16px, 5.2vw, 25px);
  font-weight: 900;
  cursor: pointer;
  touch-action: manipulation;
}
.bd-board-6 .bd-cell { font-size: clamp(21px, 7.5vw, 34px); }
.bd-cell:nth-child(6n) { border-right-color: transparent; }
.bd-board-9 .bd-cell:nth-child(9n) { border-right-color: transparent; }
.bd-board-9 .bd-cell:nth-child(6n) { border-right-color: var(--line); }
.bd-region-right { border-right: 4px solid var(--ink-line) !important; }
.bd-region-bottom { border-bottom: 4px solid var(--ink-line) !important; }
.bd-number {
  background: var(--bd-tint);
  color: var(--c1);
  cursor: default;
}
.bd-number::after {
  content: '';
  position: absolute;
  inset: 8%;
  border: 1px solid color-mix(in srgb, var(--c1) 25%, transparent);
  border-radius: 7px;
}
.bd-mine { background: color-mix(in srgb, var(--c4) 42%, white); }
.bd-safe { color: var(--ink-soft); font-size: clamp(22px, 6vw, 31px); }
.bd-hint-flash { animation: bdHint .45s ease-in-out 2; box-shadow: inset 0 0 0 3px var(--c7); z-index: 1; }
.bd-complete .bd-mine { background: color-mix(in srgb, var(--good) 27%, white); }
.bd-cycle-note { margin: 0; color: var(--ink-soft); font-size: 12px; font-weight: 850; }
@keyframes bdHint { 50% { transform: scale(.88); } }

@media (max-height: 740px) {
  .bd-rules { padding-block: 6px; }
  .bd-region-card { padding-block: 6px; }
  .bd-board-shell { width: min(78svh, 390px, 100%); }
}

/* ---------- screens ---------- */
.screen {
  position: fixed; inset: 0;
  display: none;
  flex-direction: column;
  max-width: 560px; margin: 0 auto;
  padding-top: var(--safe-t);
}
.screen.active { display: flex; }

.scroll-area {
  flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: 0 18px calc(28px + var(--safe-b));
}

/* ---------- app bar ---------- */
.app-bar {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px;
  min-height: 56px;
}
.app-bar-title {
  flex: 1;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  font-weight: 800; font-size: 18px; letter-spacing: .2px;
}
.app-bar-emoji { font-size: 20px; }
.app-bar-actions { display: flex; gap: 6px; }

.icon-btn {
  width: 42px; height: 42px; flex: none;
  border: var(--border); border-radius: 14px;
  background: var(--surface);
  color: var(--ink);
  font-size: 20px; font-weight: 800;
  box-shadow: var(--shadow);
  cursor: pointer;
  transition: transform .1s ease, box-shadow .1s ease;
}
/* Press = the paper is pushed down onto the page, so the offset shadow
   shrinks as the button moves into it. Scaling alone read as a generic
   web tap; this reads as something physical. */
.icon-btn:active {
  transform: translate(2px, 2px);
  box-shadow: 1px 1px 0 var(--ink-line);
}
.icon-btn.is-off { opacity: .45; }

/* owner-mode badge — tap to drop back to a real player's view */
.prof-btn { font-size: 22px; }
.admin-chip { white-space: nowrap; }
.admin-chip.off { opacity: .4; filter: grayscale(1); }
.admin-chip {
  align-self: center;
  padding: 7px 11px; border: none; border-radius: 999px;
  background: var(--c4); color: #fff;
  font: inherit; font-weight: 800; font-size: 11px; letter-spacing: .8px;
  box-shadow: var(--shadow); cursor: pointer;
}
.admin-chip:active { transform: scale(.92); }

/* ---------- buttons ---------- */
.btn {
  border: none; border-radius: var(--r-md);
  padding: 15px 22px;
  font: inherit; font-weight: 800; font-size: 17px;
  cursor: pointer;
  transition: transform .12s ease, filter .12s ease;
}
.btn:active { transform: translateY(2px); }
.btn-block { display: block; width: 100%; margin-top: 10px; }
/* Any explicit `display` outranks the UA stylesheet's [hidden]{display:none},
   so el.hidden = true silently does nothing on these. Restore it globally
   rather than per-component — every future .btn-block would hit this too. */
[hidden] { display: none !important; }
.btn-primary {
  background: var(--c1); color: #fff;
  box-shadow: 0 4px 0 #6a9c90;
}
.btn-primary:active { box-shadow: 0 2px 0 #6a9c90; }
.btn-ghost {
  background: transparent; color: var(--ink-soft);
  font-size: 15px; padding: 11px;
}

/* ---------- gate ---------- */
#screen-gate { justify-content: center; padding: 24px; }
.gate-box { text-align: center; }
.gate-back { position: absolute; top: calc(14px + var(--safe-t)); left: 14px; z-index: 3; }
.gate-note a { color: var(--c1); font-weight: 800; text-decoration: underline; }
.gate-logo { font-size: 64px; }
.gate-title {
  font-size: clamp(23px, 7.2vw, 34px);
  margin: 6px 0 4px;
  letter-spacing: -.5px;
  line-height: 1.02;
  white-space: nowrap;
}
.gate-sub { color: var(--ink-soft); margin: 0 0 26px; line-height: 1.5; }
.gate-input {
  width: 100%; padding: 16px;
  border: 2px solid var(--line); border-radius: var(--r-md);
  background: var(--surface); color: var(--ink);
  font: inherit; font-size: 22px; font-weight: 800;
  text-align: center; letter-spacing: 2px;
  -webkit-user-select: text; user-select: text;
}
.gate-input:focus { outline: none; border-color: var(--c1); }
.gate-error {
  color: #c4796a; font-weight: 700; font-size: 14px; margin: 12px 0 0;
}

/* ---------- feedback ---------- */
.fb-note {
  font-size: 12.5px; color: var(--ink-soft); text-align: center;
  line-height: 1.5; margin: 4px 0 16px;
}
.fb-type-row { display: flex; gap: 8px; margin-bottom: 12px; }
.fb-type {
  flex: 1; padding: 10px; border: var(--border); border-radius: var(--r-md);
  background: var(--surface); font: inherit; font-weight: 800; font-size: 13px;
  color: var(--ink-soft); cursor: pointer;
}
.fb-type.on { background: var(--c1); color: #fff; border-color: var(--c1); }
.fb-text {
  width: 100%; padding: 14px; border: 2px solid var(--line); border-radius: var(--r-md);
  background: var(--surface); color: var(--ink); font: inherit; font-size: 15px;
  resize: vertical; min-height: 90px; -webkit-user-select: text; user-select: text;
}
.fb-text:focus { outline: none; border-color: var(--c1); }
.fb-sent {
  color: var(--good); font-weight: 800; font-size: 15px; text-align: center; margin: 14px 0;
}
.gate-lang { display: flex; gap: 10px; margin-top: 28px; }
.lang-btn {
  flex: 1; padding: 11px; border: 2px solid var(--line); border-radius: var(--r-md);
  background: transparent; color: var(--ink-soft); font: inherit; font-weight: 700;
  cursor: pointer;
}
.lang-btn.active { border-color: var(--c1); background: var(--surface); color: var(--ink); }
.gate-note { color: var(--ink-soft); font-size: 12px; margin-top: 22px; line-height: 1.5; }
.terms-check {
  display: flex; align-items: flex-start; gap: 9px; margin: 14px 4px 2px;
  color: var(--ink-soft); font-size: 12px; font-weight: 700; line-height: 1.42;
  text-align: left; cursor: pointer;
}
.terms-check input { flex: 0 0 auto; width: 18px; height: 18px; margin: 0; accent-color: var(--c1); }
.terms-link {
  display: inline; padding: 0; border: 0; border-bottom: 1px dashed var(--c1);
  border-radius: 0; background: transparent; box-shadow: none; color: var(--c1);
  font: inherit; font-weight: 900; cursor: pointer;
}

/* ---------- home ---------- */
/* No bottom padding: the gap under the stat row is owned by .daily-card's
   own top margin, so the space above and below that row is the same 16px. */
.hero { padding: 4px 0 0; }
/* 900 + tight tracking: Nunito's heaviest weight is the whole reason for
   shipping the font, so the one line the child reads first should use it. */
.hero-title { font-size: 28px; margin: 0 0 4px; font-weight: 900; letter-spacing: -.5px; }
.hero-sub { color: var(--ink-soft); margin: 0; font-weight: 600; }
.hero-stats { display: flex; gap: 12px; margin-top: 16px; }
/* Shorter than it was. These three boxes are a glance, not a headline, and at
   the old size they pushed the daily card — the thing people actually came to
   tap — most of the way off a phone screen. */
.stat {
  flex: 1; background: var(--surface);
  border: var(--border); border-radius: var(--r-md);
  padding: 9px 8px; text-align: center; box-shadow: var(--shadow);
}
.stat b { display: block; font-size: 21px; font-weight: 900; line-height: 1.15; }
.stat span {
  font-size: 11px; color: var(--ink-soft); font-weight: 800;
  letter-spacing: .2px; line-height: 1.2; display: block;
}
.stat-btn { font: inherit; color: inherit; cursor: pointer; }
.stat-btn:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--ink-line); }

/* ---------- Koleksi (badges) ---------- */
.bdg-note {
  font-size: 12.5px; color: var(--ink-soft); text-align: left;
  line-height: 1.5; margin: 12px 2px;
}
.badge-summary { display:grid; grid-template-columns:1fr 1fr; gap:10px; margin:2px 0 10px; }
.badge-summary > div {
  background:linear-gradient(145deg,#fffdf7,#f4ead8); border:2px solid #dfcdb2;
  border-radius:16px; padding:12px; text-align:center;
}
.badge-summary b { display:block; font-size:18px; font-weight:900; color:#276e66; }
.badge-summary span { display:block; margin-top:2px; font-size:10.5px; font-weight:800; color:var(--ink-soft); }
.badge-tabs { display:flex; gap:7px; padding:5px; background:#eee2d2; border-radius:14px; }
.badge-tab {
  flex:1; border:0; border-radius:10px; padding:10px 8px; background:transparent;
  color:var(--ink-soft); font:inherit; font-size:12px; font-weight:900; cursor:pointer;
}
.badge-tab.on { background:var(--surface); color:#276e66; box-shadow:0 2px 7px rgba(68,50,38,.13); }
.badge-showcase-note { min-height:18px; margin:9px 2px; font-size:11px; color:#276e66; font-weight:800; }
.badge-grid {
  display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:12px; padding-bottom:16px;
}
.badge-card {
  position:relative; display:flex; flex-direction:column; align-items:center; gap:6px;
  min-width:0; min-height:190px; background:linear-gradient(160deg,#fffdf8,#f3e8d6);
  color:var(--ink); border:2px solid #dfccb0; border-radius:18px;
  box-shadow:0 5px 0 #d8c3a8; padding:12px 9px 13px; text-align:center;
  font:inherit; cursor:default;
}
.bdg-art-wrap { width:86px; height:86px; display:grid; place-items:center; }
.bdg-art { width:100%; height:100%; object-fit:contain; display:block; filter:drop-shadow(0 4px 4px rgba(46,37,29,.2)); }
.badge-art-mastery {
  position:relative; border-radius:50%; padding:var(--badge-medal-pad,7px);
  background:linear-gradient(145deg,#f9df83 0 11%,#a66a19 12% 18%,#174f4b 19% 25%,#d99f38 26% 33%,#fff1b9 34% 38%,#bc7b24 39% 100%);
  box-shadow:inset 0 0 0 2px rgba(255,248,221,.82),0 4px 7px rgba(47,42,38,.25);
}
.badge-art-mastery::after {
  content:''; position:absolute; inset:5%; border-radius:50%; pointer-events:none;
  box-shadow:inset 0 0 0 2px rgba(255,243,180,.85),inset 0 0 12px rgba(46,28,13,.28);
}
.badge-art-mastery .bdg-art,.lead-main-badge.badge-art-mastery img,.player-badge-art.badge-art-mastery img {
  width:100%; height:100%; border-radius:50%; object-fit:cover; filter:none;
}
.badge-art-elite { background:conic-gradient(from 10deg,#fff4b0,#c88520,#ffe382,#7b4312,#ffe382,#c88520,#fff4b0); }
.badge-art-elite::before {
  content:''; position:absolute; z-index:2; left:25%; right:25%; top:-13%; height:27%;
  background:linear-gradient(135deg,#d99727,#fff1a2 48%,#b36916);
  clip-path:polygon(0 100%,0 34%,25% 68%,50% 0,75% 68%,100% 34%,100% 100%);
  border-radius:2px; filter:drop-shadow(0 2px 1px rgba(61,38,12,.25));
}
.badge-card .bdg-name { display:block; font-size:12px; font-weight:900; line-height:1.25; }
.badge-card .bdg-desc { display:block; font-size:9.5px; color:var(--ink-soft); line-height:1.35; }
.bdg-featured { margin-top:auto; padding:3px 7px; border-radius:999px; background:#276e66; color:white; font-size:8.5px; font-weight:900; letter-spacing:.2px; }
.badge-card.locked { cursor:default; opacity:.5; filter:grayscale(.85); box-shadow:none; }
.bdg-locked { margin-top:auto; font-size:8.5px; font-weight:900; color:var(--ink-soft); text-transform:uppercase; letter-spacing:.5px; }
@media (min-width:620px) { .badge-grid { grid-template-columns:repeat(3,minmax(0,1fr)); } }

/* ---------- Level Otak bar ---------- */
.level-bar {
  display: flex; align-items: center; gap: 12px;
  width: 100%; margin-top: 16px;
  padding: 10px 14px;
  background: var(--surface);
  border: var(--border); border-radius: var(--r-md);
  box-shadow: var(--shadow);
  font: inherit; color: var(--ink); text-align: left; cursor: pointer;
  transition: transform .1s ease, box-shadow .1s ease;
}
.level-bar:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--ink-line); }

/* The ring is the rank. It has to be legible at avatar size, where a written
   tier name would be a grey smudge — so tier reads as colour first. */
.lv-face {
  flex: none; width: 46px; height: 46px; border-radius: 50%;
  background: var(--bg-soft);
  border: 3px solid var(--ring, var(--line));
  display: grid; place-items: center; overflow: hidden;
}
.lv-face img { width: 92%; height: 92%; object-fit: contain; display: block; }
.level-bar.glow .lv-face { box-shadow: 0 0 0 3px rgba(233,193,90,.35); }

.lv-main { flex: 1; min-width: 0; }
.lv-top { display: flex; align-items: baseline; gap: 8px; }
.lv-top b {
  font-size: 15px; font-weight: 900;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lv-top span {
  font-size: 11px; font-weight: 800; letter-spacing: .3px;
  color: var(--ink-soft); text-transform: uppercase;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lv-track {
  height: 8px; margin: 5px 0 3px;
  background: var(--bg-soft);
  border: 1.5px solid var(--ink-line); border-radius: 999px; overflow: hidden;
}
.lv-track i { display: block; height: 100%; background: var(--ring, var(--c1)); }
.lv-sub { font-size: 11px; font-weight: 700; color: var(--ink-soft); }

/* ---------- daily puzzle card ---------- */
.daily-card {
  display: flex; align-items: center; gap: 10px;
  width: 100%; margin: 16px 0 2px;
  padding: 14px 16px; min-height: 76px;
  border: var(--border); border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  font: inherit; color: #fff; text-align: left; cursor: pointer;
  position: relative; overflow: hidden;
  transition: transform .1s ease, box-shadow .1s ease;
}
.daily-card:active { transform: translate(3px, 3px); box-shadow: 2px 2px 0 var(--ink-line); }
.daily-card.has-cover { background-size: cover; background-position: center 20%; }
.daily-card.has-cover::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(to right,
    rgba(20,16,12,.80) 0%, rgba(20,16,12,.58) 55%, rgba(20,16,12,.20) 100%);
}
.daily-card > * { position: relative; z-index: 1; }
.daily-card.done { filter: saturate(.7); }

.dc-body { flex: 1; min-width: 0; }
.dc-kicker { font-size: 10.5px; font-weight: 900; letter-spacing: 1px; text-transform: uppercase; opacity: .9; }
.dc-game { font-size: 17px; font-weight: 900; margin-top: 1px; }
.dc-meta { font-size: 12px; font-weight: 700; opacity: .85; }
.dc-side { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
.dc-streak { font-size: 14px; font-weight: 900; }
.dc-cta {
  background: rgba(255,255,255,.22); border: 1.5px solid rgba(255,255,255,.5);
  border-radius: 999px; padding: 4px 12px; font-size: 12px; font-weight: 800;
  white-space: nowrap;
}

/* ---------- daily mission checklist ------------------------------------ */
.mission-card {
  margin: 14px 0 16px; padding: 0;
  background: linear-gradient(145deg, #fffaf0, #fff3dc);
  border: 2px solid #d8a54a; border-radius: var(--r-lg);
  box-shadow: 4px 4px 0 #8f6c38;
}
.mission-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.mission-toggle {
  width: 100%; padding: 12px 13px; border: 0; border-radius: inherit;
  background: transparent; color: inherit; font: inherit; text-align: left; cursor: pointer;
}
.mission-head-side { display: flex; align-items: center; gap: 7px; flex: none; }
.mission-chevron { color: var(--ink); font-size: 20px; font-weight: 900; line-height: 1; transform: rotate(0); transition: transform .15s ease; }
.mission-card.expanded .mission-chevron { transform: rotate(180deg); }
.mission-details { display: none; padding: 0 13px 12px; }
.mission-card.expanded .mission-details { display: block; }
.mission-title { font-size: 16px; font-weight: 900; color: var(--ink); }
.mission-sub { margin-top: 2px; color: var(--ink-soft); font-size: 11.5px; line-height: 1.35; }
.mission-total {
  flex: none; padding: 5px 9px; border-radius: 999px;
  background: #d99a2b; color: #fff; font-size: 11.5px; font-weight: 900;
  box-shadow: 0 2px 0 #8f641d;
}
.mission-list { display: flex; flex-direction: column; gap: 7px; }
.mission-row {
  display: grid; grid-template-columns: 25px minmax(0,1fr) auto;
  align-items: center; gap: 9px; padding: 8px 9px;
  background: rgba(255,255,255,.72); border: 1.5px solid #ead7b4; border-radius: 11px;
}
.mission-check {
  width: 23px; height: 23px; display: grid; place-items: center;
  border: 2px solid #b8965e; border-radius: 7px; color: transparent;
  background: #fff; font-size: 15px; font-weight: 1000;
}
.mission-row.done .mission-check { color: #fff; background: var(--good); border-color: #39715f; }
.mission-copy { min-width: 0; }
.mission-name { color: var(--ink); font-size: 12.5px; font-weight: 850; line-height: 1.25; }
.mission-progress { margin-top: 2px; color: var(--ink-soft); font-size: 10.5px; font-weight: 750; }
.mission-points { color: #b9780b; font-size: 11.5px; font-weight: 900; white-space: nowrap; }
.mission-row.done .mission-name { text-decoration: line-through; text-decoration-thickness: 1.5px; opacity: .72; }
.mission-row.done .mission-points { color: var(--good); }
.mission-foot { margin-top: 9px; color: var(--ink-soft); font-size: 10.5px; text-align: center; }

/* ---------- notification center ----------------------------------------- */
.notification-btn { position: relative; }
.notification-dot {
  position: absolute; right: 3px; top: 2px; min-width: 12px; height: 12px;
  border: 2px solid var(--surface); border-radius: 999px; background: #e14c4c;
  box-shadow: 0 1px 0 rgba(47,42,38,.35); pointer-events: none;
}
.notification-read-all {
  flex: none; padding: 7px 9px; border: 0; background: transparent;
  color: var(--c4); font: inherit; font-size: 10.5px; font-weight: 900;
}
.notification-read-all:disabled { opacity: .35; }
.notification-scroll { padding-top: 6px; }
.notification-intro {
  margin: 3px 2px 13px; color: var(--ink-soft); font-size: 12px; line-height: 1.45;
}
.notification-list { display: flex; flex-direction: column; gap: 10px; padding-bottom: 20px; }
.notification-item {
  position: relative; width: 100%; padding: 13px 14px; text-align: left;
  color: var(--ink); background: var(--surface); border: var(--border);
  border-radius: var(--r-md); box-shadow: var(--shadow); overflow: hidden;
}
.notification-item.unread { background: #fff9ec; border-color: #d8a54a; }
.notification-read-label { font-size:11px; font-weight:800; color:var(--ink); }
.notification-detail-card { background:var(--paper,#fffdf8);border:2px solid var(--line,#e3d5c1);border-radius:22px;padding:22px;margin:8px 0 24px; }
.notification-detail-card h2 { font-size:clamp(22px,5vw,30px);line-height:1.25;overflow-wrap:anywhere;margin:0 0 22px; }
.notification-detail-body { white-space:pre-wrap;overflow-wrap:anywhere;font-size:16px;line-height:1.75;margin-bottom:28px; }
.pk-announce-card { max-height:90dvh;overflow-y:auto!important; }
.pk-announce-copy { white-space:pre-wrap;overflow-wrap:anywhere; }
.notification-item:focus-visible { outline:3px solid var(--c1);outline-offset:3px; }
.notification-item.unread::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 5px;
  background: #e14c4c;
}
.notification-meta { display: flex; align-items: center; gap: 7px; margin-bottom: 6px; }
.notification-category {
  display: inline-flex; align-items: center; gap: 4px; padding: 3px 8px;
  border-radius: 999px; background: var(--bg-soft); color: var(--ink-soft);
  font-size: 9.5px; font-weight: 900; letter-spacing: .25px; text-transform: uppercase;
}
.notification-date { margin-left: auto; color: var(--ink-soft); font-size: 10px; font-weight: 700; }
.notification-new {
  width: 8px; height: 8px; border-radius: 50%; background: #e14c4c;
  box-shadow: 0 0 0 2px rgba(225,76,76,.15);
}
.notification-title { font-size: 15px; font-weight: 900; line-height: 1.25; }
.notification-copy {
  margin-top: 5px; color: var(--ink-soft); font-size: 12.5px; line-height: 1.5;
  white-space: pre-wrap; word-break: break-word;
}
.notification-cta {
  display: inline-flex; margin-top: 11px; padding: 7px 12px; border-radius: 999px;
  background: var(--c4); color: #fff; font-size: 11px; font-weight: 900;
  box-shadow: 0 2px 0 #225e58;
}
.notification-empty {
  min-height: 240px; display: flex; flex-direction: column; align-items: center;
  justify-content: center; text-align: center; color: var(--ink-soft); padding: 30px;
}
.notification-empty[hidden] { display: none; }
.notification-empty > span { font-size: 44px; filter: grayscale(.2); }
.notification-empty b { margin-top: 10px; color: var(--ink); font-size: 16px; }
.notification-empty p { max-width: 260px; margin: 5px 0 0; font-size: 12px; line-height: 1.45; }

.win-xp .wx-mission { margin-top: 5px; color: #b9780b; font-size: 12.5px; font-weight: 900; }
.win-xp .wx-stars,
.win-xp .wx-daily { margin-top: 3px; }
.win-xp .wx-daily { color: var(--c1); }
.challenge-daily-xp {
  margin: 10px 0 0; color: var(--c1); font-size: 15px; font-weight: 900;
}

/* ---------- XP line in the win card ---------- */
.win-xp { margin: 6px 0 2px; font-size: 15px; font-weight: 800; color: var(--ink); }
.win-xp .wx-tag {
  font-size: 11px; font-weight: 800; color: var(--ink-soft);
  background: var(--bg-soft); border-radius: 999px; padding: 2px 8px; margin-left: 4px;
}
.win-xp .wx-up { margin-top: 4px; font-size: 13px; font-weight: 900; color: var(--good); }
.win-xp .wx-badge {
  margin-top: 4px; font-size: 13px; font-weight: 800; color: var(--c4, var(--c1));
}

.xp-rows { display: flex; flex-direction: column; gap: 12px; margin: 4px 0 14px; text-align: left; }
.xp-row { display: flex; gap: 10px; align-items: flex-start; }
.xp-row span { font-size: 20px; flex: none; }
.xp-row b { display: block; font-size: 14px; }
.xp-row em { display: block; font-style: normal; font-size: 12.5px; color: var(--ink-soft); line-height: 1.45; }
.xp-note { font-size: 12px; color: var(--ink-soft); line-height: 1.5; margin: 0 0 14px; text-align: left; }

/* ---------- Otong reactions ---------- */
/* Fixed, pointer-events:none and above the modal: he reacts ON TOP of the win
   card, and must never be able to swallow the Next button underneath him. */
.otong {
  position: fixed; left: 50%; bottom: 12px;
  width: 116px; height: 116px;
  transform: translateX(-50%) translateY(24px);
  opacity: 0; pointer-events: none; z-index: 58;
  transition: opacity .18s ease, transform .18s ease;
}
.otong.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.otong.pop { animation: otong-pop .5s cubic-bezier(.34,1.56,.64,1); }
@keyframes otong-pop {
  0%   { transform: translateX(-50%) translateY(30px) scale(.7); }
  60%  { transform: translateX(-50%) translateY(-6px) scale(1.06); }
  100% { transform: translateX(-50%) translateY(0) scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .otong.pop { animation: none; }
}

/* ---------- announcement carousel ---------- */

/* ---------- owner broadcast popup ----------------------------------------
   Kept separate from the home carousel: it is a one-time, server-published
   notice, while banners are permanent navigation cards. Solid headers are
   intentional — a previous decorative white wave erased part of white titles. */
.pk-announce-modal{position:fixed;inset:0;z-index:1000;display:grid;place-items:center;padding:20px;background:rgba(47,42,38,.52);animation:pk-announce-fade .18s ease-out}
.pk-announce-card{position:relative;width:min(420px,100%);overflow:hidden;border:3px solid #fff;border-radius:24px;background:#fffdf8;box-shadow:0 18px 55px rgba(50,35,20,.34);animation:pk-announce-pop .23s ease-out}
.pk-announce-card::before,.pk-announce-card::after{content:'✦';position:absolute;z-index:2;pointer-events:none;color:#fff8b4;font-size:26px;text-shadow:0 2px 0 rgba(80,50,20,.12)}
.pk-announce-card::before{top:15px;left:20px;transform:rotate(-15deg)}
.pk-announce-card::after{top:54px;right:24px;font-size:18px;color:#fff;transform:rotate(18deg)}
.pk-announce-head{position:relative;min-height:120px;padding:24px 50px 22px 23px;color:#fff}
.pk-announce-kicker{font-size:10.5px;font-weight:900;letter-spacing:1.2px;text-transform:uppercase;opacity:.93}
.pk-announce-title{margin-top:5px;font-size:24px;line-height:1.1;font-weight:900;max-width:310px;text-shadow:0 1px 0 rgba(0,0,0,.12)}
.pk-announce-close{position:absolute;z-index:3;right:12px;top:11px;width:34px;height:34px;padding:0;border:0;border-radius:50%;background:rgba(255,255,255,.25);color:#fff;font:700 25px/1 Arial,sans-serif;cursor:pointer}
.pk-announce-body{padding:2px 23px 23px;color:var(--ink);font-size:14px;line-height:1.55;text-align:center}
.pk-announce-otong{display:block;position:relative;z-index:2;width:78px;height:78px;object-fit:contain;margin:-21px auto 4px;filter:drop-shadow(0 4px 0 rgba(65,45,30,.12))}
.pk-announce-cta{display:block;width:100%;margin-top:17px;padding:12px 16px;border:0;border-radius:999px;background:#3f7d74;color:#fff;font:800 14px/1.2 inherit;box-shadow:0 4px 0 #245c56;cursor:pointer}
.pk-announce-cta:active{transform:translateY(2px);box-shadow:0 2px 0 #245c56}
@keyframes pk-announce-fade{from{opacity:0}to{opacity:1}}
@keyframes pk-announce-pop{from{opacity:0;transform:translateY(12px) scale(.97)}to{opacity:1;transform:none}}
/* Scroll-snap rather than a JS slider: the browser already does momentum,
   rubber-banding and snapping natively on touch, and it keeps working if the
   script fails. JS only mirrors the position into the dots. */
/* ONE CARD, FULL WIDTH. This was a bleed-to-the-edge carousel with a fixed
   peek of the next slide — right when there were several banners, wrong now
   that only one is left: the peek made the single card narrower than the
   daily card and the stat row above it, which just read as a mistake. It
   still scrolls if more banners are ever added; each one is simply full
   width. */
.banners {
  display: flex; gap: 12px;
  overflow-x: auto; scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  margin: 16px 0 6px;
  padding: 2px 0 8px;
  scrollbar-width: none;
}
.banners::-webkit-scrollbar { display: none; }

.banner {
  scroll-snap-align: center;
  flex: 0 0 100%;
  position: relative; overflow: hidden;
  border: var(--border); border-radius: var(--r-lg);
  padding: 16px 18px; min-height: 104px;
  text-align: left; font: inherit; color: #fff;
  box-shadow: var(--shadow-lg); cursor: pointer;
  display: flex; flex-direction: column; justify-content: center;
  transition: transform .1s ease, box-shadow .1s ease;
}
.banner:active {
  transform: translate(3px, 3px);
  box-shadow: 2px 2px 0 var(--ink-line);
}
.banner.has-art { background-size: cover; background-position: center; }
.banner.has-art::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  /* sideways scrim: art on the right, words stay readable on the left */
  background: linear-gradient(to right,
    rgba(20,16,12,.82) 0%, rgba(20,16,12,.62) 45%, rgba(20,16,12,.15) 100%);
}
.banner > * { position: relative; z-index: 1; }
.banner .bn-title { font-weight: 800; font-size: 16px; }
.banner .bn-body { font-size: 12.5px; opacity: .9; margin-top: 3px; line-height: 1.45; }
.banner .bn-cta {
  align-self: flex-start; margin-top: 10px;
  background: rgba(255,255,255,.22); border-radius: 999px;
  padding: 5px 12px; font-size: 12px; font-weight: 800;
}

.banner-dots { display: flex; justify-content: center; gap: 6px; margin-bottom: 18px; }
.banner-dots i {
  width: 6px; height: 6px; border-radius: 999px;
  background: var(--line); transition: width .18s ease, background .18s ease;
}
.banner-dots i.on { width: 18px; background: var(--ink-soft); }

.game-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }

.game-card {
  position: relative;
  border: var(--border); border-radius: var(--r-lg);
  padding: 18px 14px 16px;
  text-align: left; font: inherit; color: #fff;
  cursor: pointer; overflow: hidden;
  box-shadow: var(--shadow-lg);
  transition: transform .1s ease, box-shadow .1s ease;
  /* ASPECT-RATIO, NOT A FIXED HEIGHT. With min-height the card kept its height
     while the width grew with the screen, so on a wide screen it became
     255x132 — and the square cover, scaled to 148% of HEIGHT, was only 195px
     wide and left 60px of bare card colour down each side. Locking the ratio
     keeps width/height at 1.25 on every device, comfortably under the 1.48
     zoom below, so the art always covers. */
  aspect-ratio: 5 / 4;
  min-height: 118px;
  display: flex; flex-direction: column; justify-content: space-between;
}
/* same physical press as the icon buttons, so the whole app shares one gesture */
.game-card:active {
  transform: translate(3px, 3px);
  box-shadow: 2px 2px 0 var(--ink-line);
}

/* COVER ART. The card keeps its solid colour as the base layer, so a missing
   or still-loading .webp degrades to exactly what shipped before rather than
   to a blank tile — art is an upgrade, never a dependency.

   The scrim is not optional. Card text is white and the art is generated, so
   nothing guarantees the area under the title stays dark: one pale corner and
   the game's name vanishes. A fixed bottom-up gradient makes legibility a
   property of the CARD rather than something all 34 images must each get right. */
.game-card.has-cover {
  /* Scaled past `cover` on purpose. At the real card size (~162x132) a plain
     `cover` on a 1:1 image leaves a wide margin of empty background showing
     above the subject — the source art always has some breathing room at the
     top, and a same-aspect crop can't cut into it. Sizing up creates crop
     slack, and `18%` position spends it mostly on the top margin while still
     showing the whole subject (Bena: "kayak count the cubes gitu nggak
     keliatan tumpukan cubesnya" — the stack was getting pushed out entirely). */
  background-size: auto 148%;
  background-position: center 18%;
  background-repeat: no-repeat;
}
/* With the icon hidden the card has a single flex child, and space-between
   parks a lone child at the START — the title jumped to the top of the card.
   Pin it to the bottom explicitly instead of relying on sibling count. */
.game-card.has-cover { justify-content: flex-end; }
.game-card.has-cover::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(to top,
    rgba(20, 16, 12, .78) 0%,
    rgba(20, 16, 12, .55) 30%,
    rgba(20, 16, 12, .10) 58%,
    rgba(20, 16, 12, 0) 78%);
}
/* lift the real content above the scrim */
.game-card > * { position: relative; z-index: 1; }
/* the art replaces the icon, so reclaim its space for the picture */
.game-card.has-cover .gc-emoji { display: none; }

.game-card .gc-emoji { font-size: 32px; line-height: 1; }
.game-card .gc-name { font-weight: 800; font-size: 17px; margin-top: auto; }
/* Hardest Wordsearch only: this cover has its own title burned into the
   art ("THE HARDEST WORDSEARCH" in flaming letters), so the usual CSS title
   would just repeat it — drop the overlay and let the art speak once.
   Position stays high (not the shared 18%) so that baked title isn't the
   part that gets cropped off. */
.game-card.gc-extreme .gc-name { display: none; }
.game-card.gc-extreme.has-cover {
  background-position: center 4%;
}
.game-card .gc-meta { font-size: 12px; opacity: .85; font-weight: 700; }
.game-card.locked { filter: grayscale(.55) opacity(.6); }
.gc-lock {
  position: absolute; top: 12px; right: 12px; font-size: 16px;
}
.gc-bar {
  height: 5px; border-radius: 3px; background: rgba(255,255,255,.35);
  margin-top: 8px; overflow: hidden;
}
.gc-bar i { display: block; height: 100%; background: #fff; border-radius: 3px; }

.footer-note {
  text-align: center; color: var(--ink-soft); font-size: 12px; margin-top: 26px;
}

/* ---------- tiers + levels ---------- */
.tier-tabs {
  display: flex; gap: 8px; margin: 4px 0 14px;
  overflow-x: auto; padding-bottom: 4px;
}
.tier-tab {
  flex: none; padding: 9px 16px; border-radius: 999px;
  border: var(--border); background: var(--surface);
  font: inherit; font-weight: 800; font-size: 14px; color: var(--ink-soft);
  cursor: pointer; white-space: nowrap;
  transition: transform .1s ease, box-shadow .1s ease;
}
.tier-tab.active {
  background: var(--accent, var(--c1)); color: #fff;
  box-shadow: var(--shadow);
}
.tier-desc { color: var(--ink-soft); font-size: 13px; margin: 0 0 16px; line-height: 1.5; }

.sync-error {
  margin: 0 0 16px; padding: 14px;
  border: 2px solid #d99b45; border-radius: var(--r-md);
  background: #fff6df; color: var(--ink); line-height: 1.45;
}
.sync-error p { margin: 6px 0 12px; color: var(--ink-soft); font-size: 13.5px; }

.level-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
.level-cell {
  aspect-ratio: 1; border: var(--border); border-radius: var(--r-md);
  background: var(--surface); box-shadow: var(--shadow);
  font: inherit; font-weight: 900; font-size: 19px; color: var(--ink);
  cursor: pointer; position: relative;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  transition: transform .1s ease, box-shadow .1s ease;
}
.level-cell:active {
  transform: translate(2px, 2px);
  box-shadow: 1px 1px 0 var(--ink-line);
}
.level-cell.done { background: var(--accent, var(--c1)); color: #fff; }
/* A locked level reads as locked from across the room: dimmed, softened, and
   visibly not a button. `cursor: default` matters as much as the blur — the
   pointer changing on hover is what tells a desktop player it is dead before
   they bother tapping. */
.level-cell.locked {
  opacity: .38;
  filter: blur(1.1px) grayscale(.55);
  cursor: default;
  box-shadow: none;
  transform: none;
}
.level-cell.locked:active { transform: none; }

/* The tab for a locked tier gets the same treatment, minus the blur — a
   blurred word is unreadable, and the player still needs to know WHICH
   difficulty they are working towards. */
.tier-tab.locked { opacity: .45; filter: grayscale(.6); cursor: default; }

.win-unlock {
  margin: 10px 0 2px; padding: 10px 12px;
  border: 2px dashed var(--ink-line); border-radius: var(--r-sm);
  background: rgba(217,164,65,.14);
  font-size: 13.5px; line-height: 1.4; text-align: center;
}
/* Gold, with a dark edge so it still reads on the pale unsolved tile as well
   as on the saturated solved one — plain white stars vanished against Easy's
   pink and plain gold vanished against the unsolved cream. */
.level-cell .lc-stars {
  font-size: 11px; letter-spacing: 1px;
  color: #f2b736; text-shadow: 0 1px 0 rgba(47,42,38,.45);
}

.shikaku-custom {
  margin: 24px 0 6px; padding: 18px;
  border: 3px solid var(--ink-line); border-radius: var(--r-lg);
  background: linear-gradient(145deg, #eef8f2, #fff7e7);
  box-shadow: var(--shadow); text-align: left;
}
.shikaku-custom h3 { margin: 0 0 7px; font-size: 21px; }
.shikaku-custom p {
  margin: 0 0 14px; color: var(--ink-soft);
  font-size: 13.5px; line-height: 1.5;
}
.shikaku-custom-choices {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 9px;
}
.shikaku-custom-choices .btn { margin: 0; padding: 11px 8px; font-size: 14px; }
.shikaku-custom small {
  display: block; margin-top: 12px; color: var(--ink-soft);
  font-weight: 700; line-height: 1.4;
}

/* COC🔥's own theme — black tile, red digit, on EVERY state (unsolved,
   solved, even locked, which still gets its usual dimming filter on top).
   The extra `.level-cell.done` in the selector is what beats
   `.level-cell.done { background: var(--accent) }` above — same
   specificity, so without it source order alone would decide, and solved
   tiles would flash orange instead of staying on-theme. Stars are
   deliberately NOT touched here — .lc-stars keeps its normal gold. */
.tier-coc-theme .level-cell,
.tier-coc-theme .level-cell.done {
  background: #000; color: #ef2020;
}

/* ---------- play ---------- */
/* The stage MUST be able to scroll. It was `overflow: visible`, so on a short
   phone anything taller than the screen was simply cut off with no way to reach
   it — the 0 / backspace / tick row of the number pad sat 31px below a 640px
   viewport and was unreachable, on Easy as much as Expert.

   `safe center` is the important half: plain `center` on a flex column pushes
   overflow off BOTH ends, so the top becomes unscrollable too. `safe` falls
   back to flex-start the moment the content does not fit. The unprefixed
   `center` above it is the fallback for browsers that do not know `safe`. */
.play-stage {
  flex: 1; display: flex; flex-direction: column;
  align-items: center;
  justify-content: center;
  justify-content: safe center;
  width: 100%; overflow-x: hidden; overflow-y: auto;
  overscroll-behavior-x: none; -webkit-overflow-scrolling: touch;
  padding: 4px 14px calc(14px + var(--safe-b)); min-height: 0;
}

/* ---------- board paper, one per category --------------------------------
   THE SURFACE VARIES, THE CONTROLS NEVER DO. Bena asked for boards that differ
   by category so they stop feeling flat. The tempting version — restyling the
   cells and buttons per category — is the wrong one: a six-year-old learns
   "tappable looks like THIS" once, and 33 dialects of that would undo it. So
   every game keeps identical controls, and only the paper underneath changes.

   All of these are gradients or one inline SVG: no image files, nothing to
   fetch, nothing that can fail offline.

   Opacity is deliberately tiny (3-7%). This sits UNDER a puzzle the child has
   to read; the moment the texture competes with the board it has failed. */
#screen-play {
  background-image:
    radial-gradient(circle at 50% 0%, color-mix(in srgb, var(--accent, var(--c1)) 14%, transparent), transparent 60%);
}

/* words — ruled notebook paper */
#screen-play[data-cat="words"] .play-stage {
  background-image: repeating-linear-gradient(
    to bottom, transparent 0 27px, rgba(63,125,116,.16) 27px 28px);
}

/* logic — graph paper */
#screen-play[data-cat="logic"] .play-stage {
  background-image:
    repeating-linear-gradient(to right,  transparent 0 21px, rgba(74,111,165,.13) 21px 22px),
    repeating-linear-gradient(to bottom, transparent 0 21px, rgba(74,111,165,.13) 21px 22px);
}

/* number — squared exercise book, bigger squares than logic */
#screen-play[data-cat="number"] .play-stage {
  background-image:
    repeating-linear-gradient(to right,  transparent 0 33px, rgba(200,145,47,.16) 33px 34px),
    repeating-linear-gradient(to bottom, transparent 0 33px, rgba(200,145,47,.16) 33px 34px);
}

/* spatial — blueprint dots */
#screen-play[data-cat="spatial"] .play-stage {
  background-image: radial-gradient(circle, rgba(63,139,147,.22) 1.4px, transparent 1.5px);
  background-size: 22px 22px;
}

/* memory — soft felt, woven at 45° */
#screen-play[data-cat="memory"] .play-stage {
  background-image:
    repeating-linear-gradient( 45deg, rgba(201,106,134,.07) 0 6px, transparent 6px 12px),
    repeating-linear-gradient(-45deg, rgba(201,106,134,.07) 0 6px, transparent 6px 12px);
}

/* deduce — detective's corkboard */
#screen-play[data-cat="deduce"] .play-stage {
  background-image:
    radial-gradient(circle at 20% 30%, rgba(141,107,80,.13) 2px, transparent 2.5px),
    radial-gradient(circle at 70% 65%, rgba(141,107,80,.10) 2.5px, transparent 3px);
  background-size: 34px 34px, 47px 47px;
}

/* solve — workshop pegboard */
#screen-play[data-cat="solve"] .play-stage {
  background-image: radial-gradient(circle, rgba(111,148,81,.20) 2px, transparent 2.5px);
  background-size: 27px 27px;
}
/* Sits under the app bar, out of the thumb zone. Laid out as a compact row so
   it costs the board as little vertical space as possible. */
.play-toolbar {
  display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;
  padding: 2px 14px 8px;
}
.tool-btn {
  min-width: 56px; padding: 7px 12px;
  border: none; border-radius: var(--r-md);
  background: var(--surface); box-shadow: var(--shadow);
  font: inherit; font-weight: 800; font-size: 11.5px; color: var(--ink);
  cursor: pointer;
  display: flex; flex-direction: row; align-items: center; gap: 5px;
}
.tool-btn:active { transform: scale(.93); }
.tool-btn { position: relative; }
.tool-btn span.ico { font-size: 15px; }
.tool-btn[disabled] { opacity: .4; }
.tool-badge {
  position: absolute; top: -6px; right: -6px;
  min-width: 20px; height: 20px; padding: 0 5px;
  border-radius: 999px; background: var(--c4); color: #fff;
  font-size: 11px; font-weight: 800; line-height: 20px; text-align: center;
}
.tool-btn.spent .tool-badge { background: var(--line); color: var(--ink-soft); }

.play-hud {
  display: flex; gap: 14px; justify-content: center; align-items: center;
  font-weight: 800; font-size: 14px; color: var(--ink-soft);
  margin-bottom: 10px;
}
.play-hud b { color: var(--ink); }

/* Count the Cubes asks its question in the HUD, where the shared 14px is sized
   for short labels like "3 left" — not for a sentence that IS the puzzle's
   instruction. Bumped and given room to breathe on its own row. */
.sp-hud { font-size: 17px; color: var(--ink); flex-wrap: wrap; row-gap: 4px; }
.sp-hud span { line-height: 1.35; }

.loading {
  color: var(--ink-soft); font-weight: 800; font-size: 15px;
  animation: breathe 1.4s ease-in-out infinite;
}
@keyframes breathe { 0%,100% { opacity: .45 } 50% { opacity: 1 } }

/* ---------- word search ---------- */
.ws-board-layout { width: 100%; max-width: 420px; min-width: 0; }
.ws-board-main {
  min-width: 0; padding: 10px;
  border: 2px solid #4f8578; border-radius: var(--r-md);
  background: rgba(255,253,249,.94);
  box-shadow: 0 3px 0 rgba(63,125,116,.16);
}
.ws-grid { display: grid; max-width: 100%; gap: 3px; touch-action: none; margin: 0 auto; }
.ws-cell {
  aspect-ratio: 1;
  display: flex; align-items: center; justify-content: center;
  background: var(--surface); border: 1px solid rgba(36,32,28,.28); border-radius: 8px;
  box-sizing: border-box;
  font-weight: 800; color: var(--ink);
  box-shadow: 0 1px 0 rgba(120,100,80,.07);
  transition: background .12s ease, color .12s ease, transform .12s ease;
}
.ws-cell.sel   { background: var(--c1); color: #fff; transform: scale(1.06); }
/* Found words keep their direction visible: horizontal = warm peach,
   vertical = mint, diagonal = lavender. The muted palette separates crossing
   paths without making a dense board shout. */
.ws-cell.found-h { background: #f8dfc6; color: #8c5829; }
.ws-cell.found-v { background: #d9eee2; color: #3f725b; }
.ws-cell.found-d { background: #e8def4; color: #695184; }
.ws-words {
  display: flex; flex-wrap: wrap; gap: 7px; justify-content: center;
  margin-top: 16px;
}
.ws-word-panel-title { display: none; }
.ws-word {
  padding: 6px 12px; border-radius: 999px;
  background: var(--surface); box-shadow: var(--shadow);
  font-weight: 800; font-size: 13px; letter-spacing: .5px;
}
.ws-word.found { text-decoration: line-through; box-shadow: none; }
.ws-word.found-h { background: #f8dfc6; color: #8c5829; }
.ws-word.found-v { background: #d9eee2; color: #3f725b; }
.ws-word.found-d { background: #e8def4; color: #695184; }
.ws-word.hinted { outline: 2px dashed var(--c4); }
.ws-landscape-hint {
  display: none; width: min(100%, 390px); margin: 14px auto 0;
  color: var(--ink-soft); font-size: 11px; font-weight: 750;
  line-height: 1.35; text-align: center;
}
@media (orientation:portrait) and (max-width:900px) {
  .ws-landscape-hint { display: block; }
}

/* This is an action instruction, not fine print. It sits against ruled paper
   and a 11px grey sentence disappeared completely on real phones, so give it
   its own soft card and a thumb cue without turning it into a large banner. */
.ws-note {
  display: flex; align-items: center; justify-content: center; gap: 7px;
  width: min(100%, 410px); margin: 0 auto 11px; padding: 7px 10px;
  border: 2px solid #4f8578; border-radius: var(--r-sm);
  background: #f7fffc; color: #285f57;
  font-size: 12.5px; font-weight: 900; line-height: 1.25; text-align: center;
  box-shadow: 0 2px 0 rgba(63,125,116,.18);
}
#ws-mode-icon { flex: none; font-size: 15px; line-height: 1; }
#ws-mode-note { min-width: 0; overflow-wrap: anywhere; }
@media (max-width:420px){.ws-note{font-size:12px;padding:7px 9px}}

/* On a wide, rotated phone/tablet the board and word list use the extra width
   instead of stretching the letter cells or making a very tall page. Portrait
   stays stacked and unchanged. */
@media (orientation:landscape) and (min-width:700px) {
  #screen-play[data-game="wordsearch"] { max-width: 920px; }
  #screen-play[data-game="wordsearch"] .play-stage { padding-inline: 20px; }
  .ws-board-layout {
    max-width: 780px; display: grid;
    grid-template-columns: minmax(300px,420px) minmax(220px,1fr);
    gap: 18px; align-items: start;
  }
  .ws-word-panel {
    min-width: 0; max-height: 420px; overflow-y: auto;
    padding: 13px; border: 2px solid var(--ink-line);
    border-radius: var(--r-md); background: rgba(255,253,249,.96);
    box-shadow: var(--shadow);
  }
  .ws-word-panel-title {
    display: block; margin-bottom: 9px; color: var(--ink-soft);
    font-size: 11px; font-weight: 900; letter-spacing: .8px;
    text-transform: uppercase;
  }
  .ws-word-panel .ws-words { margin-top: 0; justify-content: flex-start; }
  .ws-landscape-hint { display: none; }
}

/* vocabulary card — pops up when a word is found, tap a found chip to re-read */
.ws-meaning {
  margin-top: 14px; padding: 12px 15px;
  background: var(--surface); border-radius: var(--r-md);
  box-shadow: var(--shadow); text-align: left;
  max-width: 420px; width: 100%;
}
.ws-meaning b { display: block; font-size: 15px; letter-spacing: 1px; color: var(--c1); }
.ws-meaning span { display: block; font-size: 13.5px; color: var(--ink-soft); font-weight: 600; margin-top: 3px; line-height: 1.45; }

/* ---------- count the cubes ---------- */
.sp-answer {
  margin-top: 10px; min-width: 110px; padding: 10px 18px;
  background: var(--surface); border-radius: var(--r-md); box-shadow: var(--shadow);
  font-size: 30px; font-weight: 800; text-align: center; letter-spacing: 2px;
}
.sp-answer.empty { color: var(--line); }
.sp-ok { background: var(--c1); color: #fff; }
.shake { animation: shake .38s ease; }
@keyframes shake {
  0%,100% { transform: translateX(0) }
  20% { transform: translateX(-7px) }
  40% { transform: translateX(7px) }
  60% { transform: translateX(-4px) }
  80% { transform: translateX(4px) }
}

#sp-canvas, #sq-canvas { display: block; touch-action: none; }
#sq-canvas { border-radius: var(--r-lg); box-shadow: var(--shadow-lg); }

/* ---------- block slide ----------
   The board read as a bare grey rectangle with a few slabs floating on it —
   "terlalu kosong". A faint grid now shows the lanes the blocks actually run
   in, which both fills the space and explains the movement, and the blocks
   themselves get a top highlight so they look like objects rather than
   flat fills. */
.bs-board {
  position: relative;
  background:
    repeating-linear-gradient(90deg, rgba(120,100,80,.10) 0 1px, transparent 1px var(--bs-cell, 56px)),
    repeating-linear-gradient(0deg,  rgba(120,100,80,.10) 0 1px, transparent 1px var(--bs-cell, 56px)),
    var(--bg-soft);
  background-position: 6px 6px;
  border-radius: var(--r-lg); padding: 6px;
  touch-action: none;
  box-shadow: inset 0 2px 10px rgba(120,100,80,.14), var(--shadow);
}
.bs-exit {
  position: absolute;
  display: flex; align-items: center; justify-content: center;
  font-size: 22px; font-weight: 800; color: var(--c3);
  animation: beckon 1.6s ease-in-out infinite;
}
@keyframes beckon { 0%,100% { transform: translateX(0); opacity: .55 } 50% { transform: translateX(4px); opacity: 1 } }
.bs-block {
  position: absolute; border-radius: 12px;
  background: linear-gradient(#c6d1de, #b0bccd);
  box-shadow: 0 3px 0 rgba(0,0,0,.13), inset 0 2px 0 rgba(255,255,255,.55);
  cursor: grab;
}
/* a groove along the block's long axis, so which way it slides is visible */
.bs-block::after {
  content: ''; position: absolute; inset: 34% 14%;
  border-radius: 99px; background: rgba(255,255,255,.35);
}
.bs-block.tall::after { inset: 14% 34%; }
.bs-block.hero {
  background: linear-gradient(#f0b3a6, var(--c3));
  box-shadow: 0 3px 0 #c98d80, inset 0 2px 0 rgba(255,255,255,.5);
}
.bs-block .grip {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 18px;
}
.bs-block.dragging { z-index: 5; filter: brightness(1.06); }

/* ---------- maze ---------- */
.maze-wrap { position: relative; }
#maze-canvas, #pipes-canvas, #flow-canvas {
  border-radius: var(--r-lg); box-shadow: var(--shadow-lg); touch-action: none; display: block;
}
.dpad {
  display: grid; grid-template-columns: repeat(3, 56px); grid-template-rows: repeat(2, 56px);
  gap: 8px; justify-content: center; margin-top: 14px;
}
.dpad button {
  border: none; border-radius: var(--r-md); background: var(--surface);
  box-shadow: var(--shadow); font-size: 22px; font-weight: 800; color: var(--ink); cursor: pointer;
}
.dpad button:active { transform: scale(.92); }
.dpad .up   { grid-column: 2; grid-row: 1; }
.dpad .left { grid-column: 1; grid-row: 2; }
.dpad .down { grid-column: 2; grid-row: 2; }
.dpad .right{ grid-column: 3; grid-row: 2; }

/* ---------- sudoku ---------- */
/* box-sizing + max-width are the belt to the JS braces: whatever the measured
   size works out to, the board can never end up wider than the screen. The
   box-boundary margins below add width, and 1fr tracks refuse to shrink under
   their content, so without min-width:0 on the cells a grid can push past its
   own declared width. */
.sk-grid {
  display: grid; gap: 1px; margin: 0 auto;
  background: #d6cbbb; padding: 4px; border-radius: var(--r-md);
  box-sizing: border-box; max-width: 100%;
}
.sk-cell {
  aspect-ratio: 1; min-width: 0; min-height: 0;
  position: relative; display: flex; align-items: center; justify-content: center;
  background: var(--surface); border: 1px solid #d6cbbb; border-radius: 2px;
  font-weight: 800; color: var(--c8); cursor: pointer;
  box-sizing: border-box; box-shadow: none;
  transition: background .12s ease, outline .12s ease;
}
.sk-cell.fixed { color: var(--ink); background: #f4ece0; cursor: default; }
.sk-cell.sel { outline: 2px solid var(--c8); outline-offset: -1px; }
.sk-cell.bad { background: #f7dcd6; color: #c4796a; }
.sk-v { position: relative; z-index: 1; line-height: 1; }
.sk-notes {
  position: absolute; inset: 3px 4px auto 4px; z-index: 2;
  display: grid; grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 1em; align-items: start; justify-items: start;
  color: var(--c8); font-size: clamp(7px, 1.7vw, 11px);
  font-weight: 800; line-height: 1; pointer-events: none;
}
.sk-notes span { display: block; }
.sk-cell.drafted .sk-v { visibility: hidden; }
.sk-cell.drafted { background: rgba(63,139,147,.07); }
/* the extra gap marks where one box ends and the next begins — the how-to
   calls these the "bold boxes", so the split has to read at a glance. Borders
   keep every outer cell exactly the same size; the old margins made the
   boundary cells visibly smaller than their neighbours on a 9×9 board. */
.sk-cell.bl { margin-left: 0; border-left-color: var(--ink-line); }
.sk-cell.bt { margin-top: 0; border-top-color: var(--ink-line); }

.sk-pad {
  display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-top: 22px;
}
.sk-key {
  width: var(--sk-key-px, 46px); height: var(--sk-key-px, 46px);
  border: none; border-radius: var(--r-md);
  background: var(--surface); box-shadow: var(--shadow);
  font: inherit; font-weight: 800; font-size: 19px; color: var(--ink);
  cursor: pointer;
}
.sk-key:active { transform: scale(.92); }
.tool-btn.active { background: var(--c8); color: #fff; }

/* calculator block — three columns, keys big enough for a 6-year-old's thumb */
/* Fluid, not fixed. At repeat(3, 58px) plus gaps the pad was 192px wide with a
   hard width:max-content, so on a narrow phone with a tall cube stack above it
   the last row — 0, backspace and the tick — was pushed out of view entirely.
   Bena hit this on Count the Cubes hard/expert. */
.calc-pad {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px; width: min(100%, 230px); margin: 16px auto 0;
}
.calc-pad .sk-key { width: auto; height: 46px; font-size: 20px; }
.calc-pad .sp-ok { background: var(--good, #7fbf7f); color: #fff; }
.sk-erase { color: var(--ink-soft); }

/* ---------- modals ---------- */
.modal {
  position: fixed; inset: 0; z-index: 50;
  background: rgba(74,64,56,.42);
  display: flex; align-items: center; justify-content: center;
  padding: 22px;
  animation: fade .18s ease;
}
.modal[hidden] { display: none; }

/* ---------- win confetti: falling paper scraps ----------
   Sits ABOVE the win modal (z 55 vs 50) so the paper falls in front of the
   card rather than behind it — behind reads as a stuck background texture.
   pointer-events:none throughout, so it can never swallow the Next button. */
.confetti {
  position: fixed; inset: 0; z-index: 55;
  pointer-events: none; overflow: hidden;
}
.confetti i {
  position: absolute; top: -20px;
  border: 1.5px solid rgba(47,42,38,.55);   /* the same ink edge as everything else */
  border-radius: 1px;
  animation: paper-fall linear forwards;
}
@keyframes paper-fall {
  0%   { transform: translateY(0) translateX(0) rotate(0deg); opacity: 1; }
  85%  { opacity: 1; }
  100% {
    transform: translateY(105vh) translateX(var(--drift)) rotate(var(--spin));
    opacity: 0;
  }
}
.modal-card {
  position: relative;
  background: var(--surface); border-radius: var(--r-lg);
  padding: 26px 22px 20px; width: 100%; max-width: 400px;
  box-shadow: var(--shadow-lg); text-align: center;
  animation: pop .22s cubic-bezier(.2,1.2,.4,1);
  /* dvh, NOT vh. On iOS Safari `vh` is the height of the viewport WITHOUT the
     browser chrome, so 88vh is taller than what the user can actually see and
     the card runs off both ends of the screen. dvh tracks the visible area.
     The vh line stays first as a fallback for older browsers. */
  max-height: 88vh; max-height: 88dvh; overflow-y: auto;
}
/* Pinned via position:absolute against the scroll container itself (not its
   content), so it stays put in the same corner no matter how far a tall
   changelog or long feedback note pushes the rest of the card down. */
.modal-x {
  position: absolute; top: 10px; right: 10px; z-index: 2;
  width: 30px; height: 30px; border-radius: 50%; border: none;
  background: var(--bg-soft); color: var(--ink-soft);
  font-size: 16px; font-weight: 800; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.modal-x:active { transform: scale(.92); }
.modal-title { margin: 8px 0 14px; font-size: 22px; }
/* The About header is one stacked identity block, so it is set tighter
   than a normal modal title: name, handle and version read as one unit. */
.about-card .modal-title { margin: 2px 0 2px; }
.howto-emoji { font-size: 46px; }
.howto-steps {
  text-align: left; margin: 0 0 20px; padding-left: 22px;
  line-height: 1.65; color: var(--ink-soft); font-weight: 600;
}
.howto-steps li { margin-bottom: 9px; }
.howto-steps b { color: var(--ink); }
.gameinfo-meta {
  margin: -6px 0 16px; color: var(--ink-soft); font-size: 12.5px;
  font-weight: 800;
}
.gameinfo-card .howto-steps { margin-bottom: 16px; }
.gameinfo-card .btn + .btn { margin-top: 9px; }
.star-rules {
  text-align: left; background: var(--bg-soft); border-radius: var(--r-md);
  padding: 13px 15px; margin-bottom: 16px;
}
.sr-title { font-weight: 800; font-size: 13px; margin-bottom: 9px; }
.sr-row { display: flex; gap: 10px; align-items: baseline; margin-bottom: 5px; }
.sr-row span { flex: none; font-size: 11px; letter-spacing: -1px; width: 46px; }
.sr-row em { font-style: normal; font-size: 12.5px; color: var(--ink-soft); font-weight: 700; }

.play-hud .urgent, .play-hud.urgent { color: #c4796a; }
.play-hud span.urgent b { color: #c4796a; }

.win-burst { font-size: 56px; }
.win-stars {
  font-size: 34px; letter-spacing: 6px; margin: 6px 0 10px;
  color: var(--star); text-shadow: 0 2px 0 rgba(180,140,40,.25);
}
.win-msg { color: var(--ink-soft); margin: 0 0 18px; font-weight: 700; }
.win-share {
  margin: 0 0 14px; padding: 10px 11px 11px; border-radius: var(--r-md);
  background: linear-gradient(135deg, #fff0d3, #f7e7d4); border: 1px solid #e8c88d;
}
.win-share p { margin: 0 0 8px; font-size: 12.5px; font-weight: 800; color: var(--ink-soft); }
.win-share-actions { display: flex; gap: 7px; }
.btn-share-result {
  flex: 1; min-height: 39px; padding: 8px 7px; border: 2px solid var(--ink-line);
  border-radius: var(--r-sm); background: var(--surface); color: var(--ink);
  font: inherit; font-size: 12px; font-weight: 900; cursor: pointer; box-shadow: 0 3px 0 var(--ink-line);
}
.btn-share-result:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--ink-line); }

/* ---------- Target 24 ---------------------------------------------------- */
.t24-wrap { width: min(100%, 380px); margin: 0 auto; text-align: center; }
.t24-goal { display: inline-flex; align-items: center; gap: 7px; margin: 0 auto 12px; padding: 7px 13px;
  border-radius: 999px; background: #f9e5b5; color: #6c4a16; font-size: 14px; font-weight: 900; }
.t24-goal b { font-size: 24px; line-height: 1; color: #c7632f; }
.t24-status { min-height: 28px; margin: 0 0 10px; color: var(--ink-soft); font-size: 13px; font-weight: 800; }
.t24-status.bad { color: #b44e43; }
.t24-number-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 9px; margin-bottom: 12px; }
.t24-number {
  min-height: 66px; border: 2px solid var(--ink-line); border-radius: var(--r-md); background: var(--surface);
  color: var(--ink); box-shadow: 0 4px 0 rgba(72,58,49,.78); font: inherit; font-size: 27px; font-weight: 900; cursor: pointer;
}
.t24-number small { display: block; margin-top: 2px; color: var(--ink-soft); font-size: 10px; font-weight: 800; }
.t24-number.selected { background: #ffe6a9; border-color: #c78b28; transform: translateY(2px); box-shadow: 0 2px 0 rgba(72,58,49,.78); }
.t24-number:active { transform: translateY(3px); box-shadow: 0 1px 0 rgba(72,58,49,.78); }
.t24-ops { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.t24-op {
  min-height: 48px; border: 2px solid var(--ink-line); border-radius: 12px; background: #e9f2ef; color: var(--ink);
  box-shadow: 0 3px 0 rgba(72,58,49,.78); font: inherit; font-size: 24px; font-weight: 900; cursor: pointer;
}
.t24-op.selected { background: var(--c1); color: white; }
.t24-op:active { transform: translateY(2px); box-shadow: 0 1px 0 rgba(72,58,49,.78); }
.t24-expression { min-height: 30px; margin: 11px 0 5px; padding: 7px 10px; border-radius: var(--r-sm); background: rgba(255,253,249,.7); color: var(--ink-soft); font: 700 12px/1.35 inherit; overflow-wrap: anywhere; }

@keyframes fade { from { opacity: 0 } }
@keyframes pop  { from { opacity: 0; transform: scale(.9) translateY(10px) } }

/* gentle celebratory nudge, nothing flashy */
@keyframes nudge { 0%,100% { transform: none } 40% { transform: scale(1.12) } }
.pulse { animation: nudge .35s ease; }

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ---------- slide tiles ---------- */
.st-board {
  position: relative; margin: 0 auto;
  background: var(--bg-soft); border-radius: var(--r-lg);
  box-shadow: inset 0 2px 8px rgba(120,100,80,.10);
}
.st-tile {
  position: absolute; top: 0; left: 0;
  border: none; border-radius: 12px;
  background: var(--surface); color: var(--ink);
  font: inherit; font-weight: 800;
  box-shadow: 0 3px 0 rgba(120,100,80,.14);
  cursor: pointer;
  transition: transform .13s cubic-bezier(.3,1.1,.5,1);
}
.st-tile:active { filter: brightness(.96); }
.st-tile.home { background: #e2efe9; color: #4f8578; }

/* ---------- word builder ---------- */
.wb-clue {
  background: var(--surface); border-radius: var(--r-md);
  padding: 14px 16px; box-shadow: var(--shadow);
  max-width: 420px; width: 100%; text-align: left; margin-bottom: 20px;
}
.wb-label {
  display: block; font-size: 11px; font-weight: 800; letter-spacing: 1px;
  color: var(--c1); text-transform: uppercase; margin-bottom: 4px;
}
.wb-meaning { display: block; font-size: 15px; font-weight: 700; line-height: 1.45; }

.wb-slots {
  display: flex; flex-wrap: wrap; gap: 6px; justify-content: center;
  margin-bottom: 22px; cursor: pointer;
}
.wb-slot {
  width: 1.9em; height: 2.2em;
  display: flex; align-items: center; justify-content: center;
  /* a visible empty box, not a faint underline — a child needs to see how many
     letters are still missing at a glance */
  background: rgba(255,253,249,.7);
  border: 2px dashed var(--line);
  border-bottom: 3px solid var(--line);
  border-radius: 8px;
  font-weight: 800; color: var(--ink);
}
.wb-slot.filled {
  background: var(--surface); border-style: solid;
  border-color: var(--c1); box-shadow: var(--shadow);
}
.wb-slots.ok .wb-slot { background: #d9ebe5; border-bottom-color: var(--good); color: #4f8578; }

.wb-pool { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.wb-letter {
  width: 2.1em; height: 2.1em;
  border: none; border-radius: var(--r-md);
  background: var(--surface); box-shadow: var(--shadow);
  font: inherit; font-weight: 800; color: var(--ink); cursor: pointer;
}
.wb-letter:active { transform: scale(.92); }
.wb-letter.used { opacity: .25; pointer-events: none; }

/* ---------- futoshiki ---------- */
.fu-grid { position: relative; margin: 0 auto; }
.fu-cell {
  position: absolute;
  display: flex; align-items: center; justify-content: center;
  background: var(--surface); border-radius: 9px;
  /* A real outline, not a hairline shadow. On the pale panel the old cells
     were white-on-white and the grid dissolved; a dark border is what makes
     it read as a grid of boxes at a glance. */
  border: 2px solid var(--ink-line);
  font-weight: 900; color: var(--c5); cursor: pointer;
  box-shadow: 0 2px 0 rgba(74,64,56,.16);
  transition: background .12s ease, transform .12s ease;
}
.fu-cell.fixed { color: var(--ink); background: #f2ecf5; cursor: default; }
.fu-cell.sel { outline: 3px solid var(--c5); transform: scale(1.05); }
.fu-cell.bad { background: #f7dcd6; color: #c4796a; }
.fu-v { position: relative; z-index: 1; line-height: 1; }
.fu-notes,
.ks-notes,
.sv-notes {
  position: absolute; inset: 4px; z-index: 3;
  display: grid; grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 1em; align-items: start; justify-items: start;
  color: var(--c8); font-size: clamp(7px, 1.7vw, 10px);
  font-weight: 800; line-height: 1; pointer-events: none;
}
.fu-notes span,
.ks-notes span,
.sv-notes span { display: block; }
.fu-cell.drafted .fu-v,
.ks-cell.drafted .ks-v,
.sv-cell.drafted .sv-v { visibility: hidden; }
.fu-cell.drafted,
.ks-cell.drafted,
.sv-cell.drafted { background: rgba(63,139,147,.07); }
/* The comparison signs ARE the puzzle — everything else is a blank grid — so
   they are sized and weighted to be read first, not squinted at. */
.fu-sign {
  position: absolute;
  display: flex; align-items: center; justify-content: center;
  font-weight: 900; color: var(--ink);
  font-size: 22px; line-height: 1; pointer-events: none;
}

#ak-canvas { border-radius: var(--r-lg); box-shadow: var(--shadow-lg); display: block; }

/* ---------- robot commands ---------- */
#rb-canvas { border-radius: var(--r-lg); box-shadow: var(--shadow-lg); display: block; }

.rb-msg {
  min-height: 20px; margin-top: 10px;
  font-size: 13px; font-weight: 800; text-align: center;
}
.rb-msg.bad { color: #c4796a; }
.rb-msg.warn { color: var(--warn); }

/* the program the child has written, left-to-right */
.rb-prog {
  display: flex; flex-wrap: wrap; gap: 5px; justify-content: center;
  margin: 8px 0 14px; min-height: 34px;
  max-width: 420px; width: 100%;
}
.rb-chip {
  width: 32px; height: 32px;
  border: none; border-radius: 9px;
  background: var(--surface); box-shadow: var(--shadow);
  font-size: 15px; cursor: pointer; color: var(--ink);
  display: flex; align-items: center; justify-content: center;
}
.rb-chip:active { transform: scale(.9); }
.rb-chip.bad { background: #f7dcd6; box-shadow: 0 0 0 2px #c4796a; }

.rb-pad { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; }
.rb-key {
  min-width: 66px; padding: 9px 12px;
  border: none; border-radius: var(--r-md);
  background: var(--surface); box-shadow: var(--shadow);
  font: inherit; color: var(--ink); cursor: pointer;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
}
.rb-key:active { transform: scale(.94); }
.rb-ico { font-size: 18px; line-height: 1; }
.rb-lbl { font-size: 11px; font-weight: 800; }
.rb-run { background: var(--c1); color: #fff; box-shadow: 0 3px 0 #6a9c90; }

/* ---------- memory cards ---------- */
.me-grid { display: grid; margin: 0 auto; }
.me-card {
  position: relative; border: none; border-radius: 12px;
  background: var(--c7); box-shadow: var(--shadow);
  cursor: pointer; overflow: hidden; padding: 2px;
}
.me-card:active { transform: scale(.95); }
.me-back, .me-face {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  transition: opacity .16s ease;
  text-align: center; line-height: 1.1; word-break: break-word;
}
.me-back { color: #fff; font-size: 22px; font-weight: 800; opacity: 1; }
.me-face { opacity: 0; font-weight: 800; color: var(--ink); padding: 3px; }
.me-card.up { background: var(--surface); }
.me-card.up .me-back { opacity: 0; }
.me-card.up .me-face { opacity: 1; }
.me-card.done { background: #d9ebe5; box-shadow: none; }

/* ---------- number pyramid ---------- */
.py-wrap { display: flex; flex-direction: column; gap: 6px; align-items: center; }
.py-row { display: flex; justify-content: center; }
.py-brick {
  border: none; border-radius: 10px;
  background: var(--surface); box-shadow: var(--shadow);
  font: inherit; font-weight: 800; color: var(--c6); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.py-brick.fixed { background: #e7f0e4; color: var(--ink); cursor: default; }
.py-brick.sel { outline: 3px solid var(--c6); transform: scale(1.05); }
.py-brick.bad { background: #f7dcd6; color: #c4796a; }

/* ---------- crack the code ---------- */
.cb-history {
  width: 100%; max-width: 340px;
  max-height: 210px; overflow-y: auto;
  display: flex; flex-direction: column; gap: 5px; margin-bottom: 12px;
}
.cb-row {
  display: flex; align-items: center; justify-content: space-between;
  background: var(--surface); border-radius: var(--r-sm);
  padding: 5px 9px; box-shadow: 0 1px 0 rgba(120,100,80,.07);
}
.cb-reveal { background: #f4ece0; }
.cb-picks { display: flex; gap: 4px; }
.cb-chip { font-size: 19px; }
.cb-marks { display: flex; gap: 8px; font-size: 12px; font-weight: 800; }
.cb-exact { color: var(--good); }
.cb-near { color: var(--warn); }

.cb-current { display: flex; gap: 7px; justify-content: center; margin-bottom: 16px; }
.cb-slot {
  width: 46px; height: 46px;
  border: 2px dashed var(--line); border-radius: 12px;
  background: rgba(255,253,249,.7);
  font-size: 24px; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.cb-slot.filled { border-style: solid; border-color: var(--c8); background: var(--surface); }
.cb-slot.locked { border-color: var(--star); background: #fbf3dd; }

.cb-pad { display: flex; gap: 7px; justify-content: center; flex-wrap: wrap; }
.cb-key {
  width: 46px; height: 46px;
  border: none; border-radius: var(--r-md);
  background: var(--surface); box-shadow: var(--shadow);
  font-size: 24px; cursor: pointer;
}
.cb-key:active { transform: scale(.92); }
.cb-submit { background: var(--line); color: #fff; font-size: 20px; }
.cb-submit.ready { background: var(--c1); }
.cb-submit[disabled] { opacity: .5; }

/* puzzle type, so a parent can tell at a glance what a game trains */
.game-card .gc-cat {
  font-size: 10.5px; font-weight: 800; letter-spacing: .5px;
  text-transform: uppercase; opacity: .72; margin-top: 1px;
}

/* theme banner above the word grid — gives each level an identity */
.ws-theme {
  font-size: 12px; font-weight: 800; letter-spacing: 1.2px;
  color: var(--ink-soft); margin-bottom: 6px; text-transform: uppercase;
}
.ws-theme b { color: var(--c1); }

/* ---------- about ---------- */
/* THE CARD ITSELF MUST NOT SCROLL. .modal-card scrolls its whole body, and
   .modal-x is absolutely positioned inside it — so the close button scrolled
   off the top and there was no visible way out of this screen. Here the card
   is a fixed-height column that never scrolls; only the change log inside it
   does. The X stays where it is put. */
.about-card {
  text-align: center;
  display: flex; flex-direction: column;
  max-height: 86vh; max-height: 86dvh; overflow: hidden;
}
.about-logo { font-size: 30px; line-height: 1; }
.about-ver {
  display: inline-block; margin: 0 0 8px; padding: 2px 10px;
  border-radius: 999px; background: var(--bg-soft);
  font-size: 12px; font-weight: 800; color: var(--ink-soft);
}
.about-tag {
  color: var(--ink-soft); font-weight: 700; margin: 0 0 12px; font-size: 13px;
  white-space: pre-line;   /* the blank line before "- professor" is real */
}
.about-links { display: flex; gap: 7px; justify-content: center; margin-bottom: 9px; }
.about-links a {
  display: flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: var(--r-sm);
  background: var(--surface); box-shadow: var(--shadow);
  color: var(--ink); text-decoration: none; font-weight: 800; font-size: 11.5px;
}
.about-legal-row {
  flex: none; display: flex; align-items: center; justify-content: center;
  gap: 8px; margin: -2px 0 9px;
}
.about-legal-link {
  flex: none; align-self: center; margin: 0; padding: 3px 2px;
  border: 0; border-bottom: 1px dashed var(--ink-soft); border-radius: 0;
  background: transparent; box-shadow: none; color: var(--ink-soft);
  font-size: 9.5px; font-weight: 800; white-space: nowrap;
}
.legal-card { text-align: center; }
.legal-mark { color: var(--c1); font-size: 34px; font-weight: 900; line-height: 1; margin: 2px 0 8px; }
.legal-copy { color: var(--ink-soft); font-size: 13px; font-weight: 600; line-height: 1.55; text-align: left; margin: 0 0 12px; }
.legal-copy a { color: var(--c1); font-weight: 900; }
.legal-contact { margin-bottom: 16px; }
.terms-card .legal-mark { color: var(--good, #4f9f88); }
.about-sub {
  text-align: left; font-weight: 800; font-size: 13px; flex: none;
  padding-top: 10px; border-top: 2px solid var(--line); margin-bottom: 8px;
}
/* The only scrolling region on this screen, and it is CAPPED rather than
   stretched. With flex:1 it grew to fill whatever the card's 86vh left over,
   so tightening the header above it changed nothing — the card stayed the
   same height and the log just got taller. A fixed cap lets the card shrink
   to its content instead. */
.about-log {
  text-align: left; flex: 0 1 auto; min-height: 148px;
  max-height: 34vh; max-height: 34dvh; overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.log-entry { margin-bottom: 14px; }
/* ONE LINE, ALWAYS. Wrapping to two lines cost ~30px of card height, which
   came straight out of the change log's budget. Smaller type and tighter
   padding than a normal .btn, plus nowrap so it can never wrap back. */
#btn-feedback {
  flex: none; margin-top: 10px;
  padding: 12px 14px; font-size: 15px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.about-support-link {
  flex: none; margin-top: 9px; padding: 12px 14px;
  font-size: 15px; text-decoration: none;
  background: var(--c3); color: #fff;
  box-shadow: 0 4px 0 #9f4327;
}
.about-support-link:active { box-shadow: 0 2px 0 #9f4327; }
.log-head { display: flex; align-items: baseline; gap: 8px; }
.log-v {
  font-weight: 800; font-size: 12px; color: #fff;
  background: var(--c1); border-radius: 999px; padding: 2px 9px;
}
.log-date { font-size: 11px; color: var(--ink-soft); font-weight: 700; }
.log-title { font-weight: 800; font-size: 13.5px; margin: 5px 0 3px; }
.log-items { margin: 0; padding-left: 18px; }
.log-items li {
  font-size: 12.5px; color: var(--ink-soft); font-weight: 600;
  line-height: 1.5; margin-bottom: 3px;
}

/* ---------- worked-example demo ---------- */
.demo-bar {
  display: flex; align-items: center; gap: 10px;
  margin: 0 14px 6px; padding: 10px 14px;
  background: var(--c1); color: #fff; border-radius: var(--r-md);
  box-shadow: var(--shadow); font-weight: 800; font-size: 13px;
  animation: fade .2s ease;
}
.demo-bar[hidden] { display: none; }
#demo-say { flex: 1; line-height: 1.35; }
.demo-stop {
  flex: none; border: none; border-radius: 999px;
  background: rgba(255,255,255,.25); color: #fff;
  font: inherit; font-weight: 800; font-size: 12px;
  padding: 5px 12px; cursor: pointer;
}
/* the hand that shows where the demo is "touching" */
.demo-ghost {
  position: fixed; z-index: 40; pointer-events: none;
  width: 30px; height: 30px; margin: -15px 0 0 -15px;
  border-radius: 50%; border: 3px solid var(--c1);
  background: rgba(127,181,168,.28);
  transition: left .28s ease, top .28s ease;
}

/* ---------- star store ---------- */
.wallet {
  display: flex; align-items: center; gap: 14px;
  background: var(--c1); color: #fff;
  border-radius: var(--r-lg); padding: 16px 18px; margin-bottom: 14px;
  box-shadow: var(--shadow-lg);
}
.wallet-main { flex: 1; }
.wallet-main b { display: block; font-size: 34px; line-height: 1; }
.wallet-main span { font-size: 12px; font-weight: 800; opacity: .9; }
.wallet-side { display: flex; flex-direction: column; gap: 6px; text-align: right; }
.wallet-side b { font-size: 15px; }
.wallet-side span { font-size: 10.5px; font-weight: 700; opacity: .8; margin-left: 5px; }


.store-note { color: var(--ink-soft); font-size: 12.5px; margin: 0 0 16px; line-height: 1.5; }
.store-list { display: flex; flex-direction: column; gap: 10px; }

.store-row {
  display: flex; align-items: center; gap: 12px;
  background: var(--surface); border-radius: var(--r-md);
  padding: 12px 14px; box-shadow: var(--shadow);
  cursor: pointer;
}
.store-row:focus-visible { outline: 3px solid var(--c2); outline-offset: 2px; }
.store-row.owned { opacity: .62; }
.sr-icon {
  width: 44px; height: 44px; flex: none; border-radius: 12px;
  display: flex; align-items: center; justify-content: center; font-size: 22px;
}
.sr-body { flex: 1; min-width: 0; }
.sr-name { font-weight: 800; font-size: 14.5px; }
.sr-cat {
  font-size: 10.5px; font-weight: 800; letter-spacing: .5px;
  text-transform: uppercase; color: var(--ink-soft); margin-top: 1px;
}
.sr-buy {
  flex: none; border: none; border-radius: var(--r-md);
  padding: 9px 14px; font: inherit; font-weight: 800; font-size: 13px;
  background: var(--c1); color: #fff; cursor: pointer;
  box-shadow: 0 3px 0 #6a9c90;
}
.sr-buy:active { transform: translateY(2px); box-shadow: 0 1px 0 #6a9c90; }
.sr-buy.cant { background: var(--line); color: var(--ink-soft); box-shadow: none; }
.sr-have { flex: none; font-size: 12px; font-weight: 800; color: var(--good); }
.sr-buy.equipped { background: var(--good); box-shadow: 0 3px 0 #4a8a5a; }
.sr-icon img.sr-glyph { width: 30px; height: 30px; object-fit: contain; }

/* the moment a purchase lands */
.buy-flash { animation: buyflash .6s ease; }
@keyframes buyflash {
  0% { transform: scale(1) }
  35% { transform: scale(1.04); box-shadow: 0 0 0 3px var(--c1) }
  100% { transform: scale(1) }
}

/* ---------- parent account ---------- */
#screen-account {
  max-width: none; justify-content: flex-start; overflow-x: hidden; overflow-y: auto;
  -webkit-overflow-scrolling: touch; padding: 0;
}
.acct-page {
  width: min(1120px, 100%); min-height: 100%; margin: 0 auto;
  padding: calc(20px + var(--safe-t)) 18px calc(24px + var(--safe-b));
}
.acct-layout { display: block; }
.acct-marketing {
  min-width: 0; display: grid; gap: 16px; align-items: center;
  padding: 20px 18px; background: rgba(255,253,249,.92);
  border: 3px solid var(--ink-line); border-radius: 28px; box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.acct-hero-text { min-width: 0; }
.acct-brand-lockup { display: flex; align-items: center; gap: 10px; margin-bottom: 18px; }
.acct-brand-lockup img { width: 64px; height: 64px; object-fit: contain; flex: none; }
.acct-brand-lockup strong,
.acct-brand-lockup span { display: block; font-weight: 1000; line-height: .92; letter-spacing: .8px; }
.acct-brand-lockup strong { font-size: 22px; }
.acct-brand-lockup span { color: var(--c1); font-size: 15px; letter-spacing: 4px; margin-top: 5px; }
.acct-brand-lockup small { display: block; color: var(--ink-soft); font-size: 11px; font-weight: 800; margin-top: 7px; }
.acct-eyebrow,
.acct-section-kicker {
  margin: 0 0 8px; color: var(--c1); font-size: 11px; font-weight: 1000;
  letter-spacing: 1.5px; line-height: 1.3;
}
.acct-hero-text > h1 {
  max-width: 10ch; margin: 0; color: var(--ink-line);
  font-size: clamp(42px, 12.5vw, 64px); font-weight: 1000; line-height: .93;
  letter-spacing: -2.3px;
}
.acct-hero-copy {
  max-width: 60ch; margin: 18px 0 0; color: var(--ink); font-size: 16px;
  font-weight: 700; line-height: 1.58;
}
.acct-demo-cta {
  width: fit-content; min-height: 48px;
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  margin-top: 16px; padding: 11px 17px;
  border: 3px solid var(--ink-line); border-radius: var(--r-md);
  background: var(--c4); box-shadow: 4px 4px 0 var(--ink-line);
  color: var(--ink-line); font-size: 14px; font-weight: 1000;
  text-decoration: none;
}
.acct-demo-cta span {
  width: 25px; height: 25px; display: grid; place-items: center;
  border: 2px solid var(--ink-line); border-radius: 50%; background: var(--surface);
  font-size: 10px; line-height: 1;
}
.acct-demo-cta:active { transform: translate(2px,2px); box-shadow: 2px 2px 0 var(--ink-line); }
.acct-cover-deck {
  position: relative; width: min(100%, 390px); height: 220px;
  margin: 0 auto; isolation: isolate; overflow: hidden;
}
.acct-cover-card {
  position: absolute; width: clamp(122px, 41vw, 160px); height: auto; aspect-ratio: 1;
  object-fit: cover; border: 3px solid var(--ink-line); border-radius: 19px;
  box-shadow: var(--shadow-lg); background: var(--surface); transform-origin: center;
}
.acct-cover-maze { left: 2%; top: 34px; transform: rotate(-8deg); }
.acct-cover-wordsearch { left: 50%; top: 2px; z-index: 2; transform: translateX(-50%) rotate(2deg); }
.acct-cover-sudoku { right: 2%; top: 35px; transform: rotate(8deg); }
.acct-usp-list {
  display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 9px;
  margin: 14px 0 0; padding: 0; list-style: none;
}
.acct-usp-list li {
  min-height: 44px; display: flex; align-items: center; justify-content: center;
  flex-direction: column;
  padding: 9px 10px; background: var(--surface); border: 2px solid var(--ink-line);
  border-radius: 999px; box-shadow: 2px 2px 0 var(--ink-line);
  font-size: 12px; font-weight: 1000; text-align: center;
}
.acct-usp-list strong { font: inherit; }
.acct-usp-list small {
  display: block; margin-top: 2px; color: var(--ink-soft); font-size: 9.5px;
  font-weight: 800; line-height: 1.15;
}
.acct-entry-grid { display: grid; gap: 18px; margin-top: 20px; align-items: start; }
.acct-onboarding {
  margin: 0; padding: 20px 17px; background: #fff3c4;
  border: 3px solid var(--ink-line); border-radius: var(--r-lg); box-shadow: var(--shadow-lg);
}
.acct-onboarding h2,
.acct-auth-heading h2 { margin: 0; color: var(--ink-line); font-size: 26px; line-height: 1.08; }
.acct-onboarding-copy,
.acct-auth-heading > p:last-child {
  margin: 9px 0 0; color: var(--ink-soft); font-size: 13px; line-height: 1.5;
}
.acct-steps {
  display: grid; grid-template-columns: repeat(3,minmax(0,1fr)); gap: 8px;
  margin: 16px 0; padding: 0; list-style: none;
}
.acct-steps li {
  min-width: 0; padding: 11px 5px; background: rgba(255,253,249,.76);
  border: 2px solid var(--ink-line); border-radius: 14px; text-align: center;
}
.acct-steps span {
  width: 28px; height: 28px; display: grid; place-items: center; margin: 0 auto 6px;
  border-radius: 50%; background: var(--c4); color: var(--ink-line); font-weight: 1000;
}
.acct-steps b { display: block; font-size: 11px; line-height: 1.25; }
.acct-access-cta {
  min-height: 52px; display: flex; align-items: center; justify-content: center;
  padding: 13px 16px; background: var(--c4); border: 3px solid var(--ink-line);
  border-radius: var(--r-md); box-shadow: 4px 4px 0 var(--ink-line);
  color: var(--ink-line); font-size: 15px; font-weight: 1000; text-align: center;
  text-decoration: none;
}
.acct-access-cta:active { transform: translate(2px,2px); box-shadow: 2px 2px 0 var(--ink-line); }
.acct-access-note { margin: 12px 0 0; color: #695838; font-size: 11.5px; line-height: 1.45; }
.acct-auth-card {
  min-width: 0; padding: 22px 18px; background: rgba(255,253,249,.97);
  border: 3px solid var(--ink-line); border-radius: 26px; box-shadow: var(--shadow-lg);
}
.acct-auth-heading { margin-bottom: 18px; text-align: left; }
.acct-tabs {
  display: flex; gap: 8px; margin: 0 0 16px;
  background: var(--bg-soft); border: 2px solid var(--line); border-radius: var(--r-md); padding: 4px;
}
.acct-tab {
  min-height: 44px; flex: 1; padding: 10px; border: none; border-radius: 12px;
  background: transparent; font: inherit; font-weight: 800; font-size: 14px;
  color: var(--ink-soft); cursor: pointer;
}
.acct-tab.on { background: var(--surface); color: var(--ink); box-shadow: var(--shadow); }
.acct-input {
  min-height: 50px; font-size: 16px; letter-spacing: 0; text-align: left; margin-bottom: 10px;
  border-color: var(--ink-line);
}
.acct-field-label {
  display: block; margin: 3px 2px 7px; color: var(--ink); font-size: 13px;
  font-weight: 900; text-align: left;
}
.acct-signup-review {
  width: 100%; padding: 22px 17px; background: var(--surface);
  border: 3px solid var(--c1); border-radius: var(--r-lg);
  text-align: center;
}
.acct-review-step {
  margin: 0 0 8px; color: var(--c1); font-size: 12px; font-weight: 900;
  letter-spacing: 1.5px; text-transform: uppercase;
}
.acct-signup-review h2 { margin: 0 0 14px; font-size: clamp(23px,6vw,30px); line-height: 1.15; }
.acct-review-email {
  margin: 0 0 14px; padding: 15px 12px; background: var(--bg-soft);
  border: 2px dashed var(--c1); border-radius: var(--r-md); color: var(--ink);
  font-size: clamp(18px,5vw,24px); font-weight: 900; overflow-wrap: anywhere;
}
.acct-review-note { margin: 0 0 18px; color: var(--ink-soft); font-size: 13px; line-height: 1.55; }
.acct-review-edit {
  width: 100%; min-height: 44px; margin: 12px 0 0; padding: 10px; border: 0; background: none;
  color: var(--c1); font: inherit; font-size: 14px; font-weight: 900;
  text-decoration: underline; text-underline-offset: 3px; cursor: pointer;
}
.acct-created-icon { margin-bottom: 8px; font-size: 52px; }
.acct-utility {
  margin-top: 16px; padding-top: 14px; border-top: 2px dashed var(--line); text-align: left;
}
.acct-utility-label { display: block; margin-bottom: 8px; color: var(--ink-soft); font-size: 11px; font-weight: 900; }
.acct-utility-actions { display: flex; gap: 8px; align-items: stretch; }
.acct-footer {
  display: flex; align-items: center; justify-content: center; flex-wrap: wrap;
  gap: 10px 16px; margin: 24px 0 0;
}
.acct-footer .footer-note { margin: 0; }
.acct-social-links { display: flex; align-items: center; justify-content: center; gap: 8px; }
.acct-social-link {
  width: 44px; height: 44px; display: grid; place-items: center; flex: none;
  color: var(--ink); background: var(--surface); border: 2px solid var(--ink-line);
  border-radius: 50%; box-shadow: 2px 2px 0 var(--ink-line); text-decoration: none;
}
.acct-social-link svg {
  width: 22px; height: 22px; fill: none; stroke: currentColor;
  stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round;
}
.acct-social-link:active { transform: translate(1px,1px); box-shadow: 1px 1px 0 var(--ink-line); }
#screen-account a:focus-visible,
#screen-account button:focus-visible,
#screen-account input:focus-visible {
  outline: 3px solid var(--c2); outline-offset: 3px;
}
@media (min-width: 820px) {
  .acct-page { padding: calc(34px + var(--safe-t)) 28px calc(28px + var(--safe-b)); }
  .acct-marketing {
    grid-template-columns: minmax(0,1fr) minmax(340px,.85fr);
    gap: 28px; min-height: 302px; padding: 26px 30px;
  }
  .acct-hero-text > h1 { font-size: clamp(48px,5vw,64px); }
  .acct-cover-deck { width: 100%; height: 250px; }
  .acct-cover-card { width: 168px; border-radius: 22px; }
  .acct-cover-maze { left: 10px; top: 42px; }
  .acct-cover-wordsearch { top: 10px; }
  .acct-cover-sudoku { right: 10px; top: 44px; }
  .acct-usp-list { grid-template-columns: repeat(4,minmax(0,1fr)); }
  .acct-usp-list li { border-radius: 15px; }
  .acct-entry-grid { grid-template-columns: minmax(0,1fr) minmax(380px,1fr); gap: 22px; }
  .acct-auth-card { padding: 27px 24px; }
}
@media (max-width: 420px) {
  .acct-page { padding-left: 12px; padding-right: 12px; }
  .acct-brand-lockup { margin-bottom: 20px; }
  .acct-brand-lockup img { width: 56px; height: 56px; }
  .acct-brand-lockup strong { font-size: 19px; }
  .acct-hero-text > h1 { font-size: clamp(38px,12.5vw,48px); }
  .acct-hero-copy { font-size: 14.5px; }
  .acct-cover-deck { height: 190px; }
  .acct-cover-card { width: clamp(112px,40vw,140px); }
  .acct-cover-maze { left: 4px; top: 30px; }
  .acct-cover-wordsearch { top: 4px; }
  .acct-cover-sudoku { right: 4px; top: 31px; }
  .acct-onboarding { padding: 18px 14px; }
  .acct-auth-card { padding: 20px 15px; }
  .acct-signup-review { padding: 20px 14px; }
  .acct-utility-actions { flex-direction: column; }
  .acct-footer { flex-direction: column; }
}
@media (prefers-reduced-motion: reduce) {
  #screen-account *, #screen-account *::before, #screen-account *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important; scroll-behavior: auto !important;
  }
}

/* ---------- public homepage preview v2 ----------
   The logged-out page is a shop window first and an account form second.
   It shows the product through light CSS motion instead of autoplay video,
   keeping the first visit quick on mobile data and respecting reduced-motion. */
#screen-account { scroll-behavior: smooth; }
.acct-page { width: min(1180px,100%); padding-top: calc(12px + var(--safe-t)); }
.acct-topbar {
  min-height: 58px; display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 12px; padding: 4px 3px;
}
.acct-mini-brand { display: flex; align-items: center; gap: 8px; color: var(--ink-line); text-decoration: none; }
.acct-mini-brand img { width: 42px; height: 42px; object-fit: contain; }
.acct-mini-brand b { display: block; font-size: 15px; font-weight: 1000; letter-spacing: .7px; line-height: 1; }
.acct-mini-brand small { display: block; margin-top: 4px; color: var(--c1); font-size: 9px; font-weight: 1000; letter-spacing: 2.8px; }
.acct-top-actions { display: flex; align-items: center; gap: 5px; }
.acct-top-actions a {
  min-height: 44px; display: inline-flex; align-items: center; justify-content: center;
  padding: 9px 11px; border-radius: 13px; color: var(--ink); font-size: 12px;
  font-weight: 1000; text-decoration: none;
}
.acct-top-actions a.primary { background: var(--ink-line); color: #fff; padding-inline: 14px; }

.acct-marketing.acct-hero {
  min-height: 620px; display: grid; grid-template-columns: minmax(0,1fr); gap: 28px;
  padding: 30px 20px 0; border: 0; border-radius: 32px; overflow: hidden;
  background:
    radial-gradient(circle at 92% 8%, rgba(255,255,255,.95), transparent 28%),
    linear-gradient(145deg,#dcefeb 0%,#f4e8cf 55%,#f8dccd 100%);
  box-shadow: none;
}
.acct-hero-text { position: relative; z-index: 3; }
.acct-eyebrow { margin-bottom: 12px; color: #236e67; font-size: 11px; letter-spacing: 1.7px; }
.acct-hero-text > h1 { max-width: 12ch; font-size: clamp(42px,12.6vw,68px); line-height: .95; letter-spacing: -2.4px; }
.acct-hero-text > h1 em { color: var(--c3); font-style: normal; }
.acct-hero-copy { max-width: 49ch; margin-top: 18px; color: #554b43; font-size: 16px; font-weight: 650; line-height: 1.55; }
.acct-hero-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 14px; margin-top: 20px; }
.acct-demo-cta { min-height: 56px; margin: 0; padding: 12px 22px; border-width: 2px; border-radius: 16px; font-size: 16px; box-shadow: 3px 3px 0 var(--ink-line); }
.acct-text-cta { min-height: 44px; display: inline-flex; align-items: center; color: var(--ink-line); font-size: 14px; font-weight: 1000; text-underline-offset: 4px; }
.acct-hero-proof { display: flex; gap: 0; margin: 23px 0 0; padding: 0; list-style: none; }
.acct-hero-proof li { min-width: 0; padding: 0 12px; border-left: 1px solid rgba(47,42,38,.25); }
.acct-hero-proof li:first-child { padding-left: 0; border-left: 0; }
.acct-hero-proof b { display: block; color: var(--ink-line); font-size: 18px; font-weight: 1000; line-height: 1; }
.acct-hero-proof span { display: block; margin-top: 4px; color: #74675e; font-size: 10px; font-weight: 800; }

.acct-hero-visual { position: relative; min-height: 315px; margin: 0 -4px; }
.acct-phone {
  position: absolute; z-index: 2; left: 50%; bottom: -38px; width: 235px; min-height: 342px;
  padding: 18px 14px; transform: translateX(-50%) rotate(-2deg);
  background: #fffdf9; border: 7px solid var(--ink-line); border-bottom: 0;
  border-radius: 31px 31px 0 0; box-shadow: 0 22px 45px rgba(47,42,38,.22);
}
.acct-phone::before { content:""; position:absolute; width:68px; height:8px; left:50%; top:5px; transform:translateX(-50%); border-radius:99px; background:var(--ink-line); }
.acct-phone-top { display: flex; align-items: center; justify-content: space-between; gap: 7px; margin: 5px 0 16px; font-size: 11px; }
.acct-phone-top span { width: 27px; height: 27px; display: grid; place-items: center; border: 2px solid var(--ink-line); border-radius: 9px; font-weight: 1000; }
.acct-phone-top b { white-space: nowrap; }
.acct-shikaku-board {
  position: relative; width: 100%; aspect-ratio: 1; overflow: hidden; border: 3px solid var(--ink-line); border-radius: 13px;
  background-color: #fbf6eb;
  background-image: linear-gradient(rgba(47,42,38,.17) 1px,transparent 1px),linear-gradient(90deg,rgba(47,42,38,.17) 1px,transparent 1px);
  background-size: 16.667% 16.667%;
}
.acct-shikaku-board i { position: absolute; display: block; border: 3px solid; border-radius: 4px; opacity: .9; transform: scale(.94); animation: acct-area-in 5s ease-in-out infinite; }
.acct-shikaku-board .a { left:0; top:0; width:50%; height:33.333%; color:#d9683f; background:#f8d7ca; }
.acct-shikaku-board .b { right:0; top:0; width:50%; height:50%; color:#3f7d74; background:#dcefeb; animation-delay:.5s; }
.acct-shikaku-board .c { left:0; top:33.333%; width:33.333%; height:66.667%; color:#8d6bb0; background:#eadff1; animation-delay:1s; }
.acct-shikaku-board .d { left:33.333%; bottom:0; width:66.667%; height:50%; color:#c8912f; background:#f6e7bd; animation-delay:1.5s; }
.acct-shikaku-board .e { left:33.333%; top:33.333%; width:16.667%; height:16.667%; color:#6f9451; background:#dfe9d4; animation-delay:2s; }
.acct-shikaku-board b { position:absolute; z-index:2; font-size:12px; }
.acct-shikaku-board .n1{left:21%;top:12%}.acct-shikaku-board .n2{right:22%;top:18%}.acct-shikaku-board .n3{left:10%;bottom:25%}.acct-shikaku-board .n4{left:39%;top:39%}.acct-shikaku-board .n5{right:20%;bottom:20%}
.acct-phone-progress { height: 8px; margin: 14px 3px 8px; overflow: hidden; border-radius: 99px; background: var(--line); }
.acct-phone-progress span { display: block; width: 72%; height: 100%; border-radius: inherit; background: var(--c1); }
.acct-phone > p { margin: 0; color: var(--ink-soft); font-size: 10px; font-weight: 900; text-align: center; }
.acct-hero-otong { position: absolute; z-index: 4; right: calc(50% - 176px); bottom: -1px; width: 101px; height: auto; filter: drop-shadow(0 8px 5px rgba(47,42,38,.18)); }
.acct-floating-cover { position: absolute; z-index: 1; width: 93px; aspect-ratio:1; overflow:hidden; border: 4px solid #fff; border-radius: 21px; box-shadow: 0 12px 25px rgba(47,42,38,.20); }
.acct-floating-cover img { width:100%; height:100%; display:block; object-fit:cover; }
.acct-floating-cover.one { left: 2px; bottom: 78px; transform: rotate(-10deg); }
.acct-floating-cover.two { right: 2px; top: 25px; transform: rotate(10deg); }

.acct-showcase,.acct-variety,.acct-fit { margin-top: 68px; }
.acct-section-head { max-width: 560px; margin: 0 auto 22px; text-align: center; }
.acct-section-head.compact { margin-bottom: 20px; }
.acct-section-head h2 { margin: 0; color: var(--ink-line); font-size: clamp(31px,8.8vw,48px); font-weight: 1000; letter-spacing: -1.3px; line-height: 1.02; }
.acct-section-head > p:last-child { margin: 12px 0 0; color: var(--ink-soft); font-size: 14px; font-weight: 700; line-height: 1.5; }
.acct-motion-rail {
  display: grid; grid-auto-flow: column; grid-auto-columns: min(82vw,310px); gap: 13px;
  margin: 0 -18px; padding: 4px 18px 16px; overflow-x: auto; scroll-snap-type: x mandatory;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.acct-motion-rail::-webkit-scrollbar,.acct-cover-rail::-webkit-scrollbar { display:none; }
.acct-motion-card {
  scroll-snap-align: center; overflow: hidden; padding: 10px 10px 16px;
  border: 2px solid var(--ink-line); border-radius: 25px; background: var(--surface);
  box-shadow: 3px 3px 0 var(--ink-line);
}
.acct-motion-stage { position: relative; height: 250px; overflow: hidden; border-radius: 17px; background: #e6f2ee; }
.acct-motion-card > div:last-child { padding: 14px 6px 0; }
.acct-motion-card small { color: var(--c1); font-size: 10px; font-weight: 1000; letter-spacing: 1.5px; }
.acct-motion-card h3 { margin: 4px 0 0; color: var(--ink-line); font-size: 19px; line-height: 1.15; }
.acct-word-grid { position:absolute; inset:23px; display:grid; grid-template-columns:repeat(4,1fr); gap:5px; }
.acct-word-grid span { display:grid; place-items:center; border:1.5px solid rgba(47,42,38,.35); border-radius:9px; background:#fff; font-size:17px; font-weight:1000; }
.acct-word-swipe { position:absolute; left:35px; top:96px; width:194px; height:42px; border:3px solid #c67851; border-radius:99px; background:rgba(241,179,139,.42); transform-origin:left center; animation:acct-word-find 3.7s ease-in-out infinite; }
.acct-pipe-stage { background:#f7e5c0; }
.acct-pipe-stage i { position:absolute; display:grid; place-items:center; width:67px; height:67px; color:#4c8c91; font:900 58px/1 monospace; font-style:normal; }
.acct-pipe-stage .pipe-a{left:30px;top:35px}.acct-pipe-stage .pipe-b{left:93px;top:35px}.acct-pipe-stage .pipe-c{left:155px;top:35px}.acct-pipe-stage .pipe-d{left:155px;top:98px;animation:acct-pipe-turn 3.4s ease-in-out infinite}
.acct-pipe-stage .tap { position:absolute; z-index:2; right:45px; bottom:44px; font-size:35px; animation:acct-tap 3.4s ease-in-out infinite; }
.acct-pipe-stage .water { position:absolute; left:49px; top:69px; width:139px; height:5px; border-radius:99px; background:#5cc5db; animation:acct-water 3.4s ease-in-out infinite; }
.acct-motion-card.sudoku .acct-motion-stage { background:#e4edf4; }
.acct-sudoku-grid { position:absolute; inset:25px; display:grid; grid-template-columns:repeat(3,1fr); border:3px solid var(--ink-line); background:var(--ink-line); gap:2px; }
.acct-sudoku-grid span { display:grid; place-items:center; background:#fff; color:#355f88; font-size:28px; font-weight:900; }
.acct-sudoku-pop { position:absolute; left:50%; top:50%; width:58px; height:58px; display:grid; place-items:center; transform:translate(-50%,-50%); border-radius:12px; background:#fff3c4; color:#d9683f; font-size:29px; animation:acct-number-pop 3s ease-in-out infinite; }
.acct-motion-card.count .acct-motion-stage { background:#e9e0f0; }
.acct-cubes { position:absolute; left:50%; top:49%; width:145px; height:130px; transform:translate(-50%,-50%); }
.acct-cubes i { position:absolute; width:55px; height:55px; border:3px solid var(--ink-line); background:#79b7bc; transform:rotate(30deg) skewY(-30deg) scaleY(.86); }
.acct-cubes i:nth-child(1){left:10px;top:55px}.acct-cubes i:nth-child(2){left:53px;top:55px}.acct-cubes i:nth-child(3){left:96px;top:55px}.acct-cubes i:nth-child(4){left:32px;top:19px}.acct-cubes i:nth-child(5){left:75px;top:19px}.acct-cubes i:nth-child(6){left:54px;top:-18px}
.acct-count-bubble { position:absolute; right:15px; top:14px; padding:8px 12px; border:2px solid var(--ink-line); border-radius:99px; background:#fff; font-size:11px; font-weight:1000; animation:acct-bob 2.4s ease-in-out infinite; }

.acct-variety { padding: 34px 0 30px; border-radius: 30px; background: #2f2a26; color:#fff; }
.acct-variety .acct-section-head h2,.acct-variety .acct-section-kicker { color:#fff; }
.acct-variety .acct-section-kicker { opacity:.64; }
.acct-cover-rail { display:flex; gap:12px; padding:0 18px 18px; overflow-x:auto; scroll-snap-type:x mandatory; scrollbar-width:none; }
.acct-cover-rail figure { width:142px; flex:none; margin:0; scroll-snap-align:start; }
.acct-cover-rail img { width:142px; height:142px; display:block; object-fit:cover; border:3px solid #fff; border-radius:20px; }
.acct-cover-rail figcaption { margin-top:8px; color:#fff; font-size:12px; font-weight:900; text-align:center; }
.acct-inline-link { min-height:48px; width:fit-content; display:flex; align-items:center; justify-content:center; margin:4px auto 0; padding:8px 17px; border-radius:99px; background:#fff; color:var(--ink-line); font-size:13px; font-weight:1000; text-decoration:none; }

.acct-fit-grid { display:grid; gap:11px; }
.acct-fit-grid article { padding:20px 18px; border:1.5px solid var(--line); border-radius:21px; background:rgba(255,253,249,.86); }
.acct-fit-grid article > span { width:42px; height:42px; display:grid; place-items:center; border-radius:13px; background:var(--bg-soft); font-size:21px; }
.acct-fit-grid h3 { margin:12px 0 4px; color:var(--ink-line); font-size:17px; }
.acct-fit-grid p { margin:0; color:var(--ink-soft); font-size:13px; font-weight:650; line-height:1.45; }

.acct-try-strip { position:relative; min-height:255px; display:flex; flex-direction:column; align-items:flex-start; justify-content:center; gap:15px; margin-top:62px; padding:30px 142px 30px 22px; overflow:hidden; border-radius:28px; background:#ef9b69; color:var(--ink-line); }
.acct-try-strip > img { position:absolute; right:-28px; bottom:-8px; width:178px; height:auto; }
.acct-try-strip p { margin:0 0 5px; font-size:12px; font-weight:1000; letter-spacing:1px; text-transform:uppercase; }
.acct-try-strip h2 { margin:0; font-size:30px; line-height:1.02; letter-spacing:-.8px; }
.acct-try-strip a { min-height:50px; display:inline-flex; align-items:center; gap:13px; padding:11px 17px; border:2px solid var(--ink-line); border-radius:14px; background:#fff; color:var(--ink-line); box-shadow:3px 3px 0 var(--ink-line); font-size:14px; font-weight:1000; text-decoration:none; }

.acct-entry-grid { margin-top: 62px; }
.acct-onboarding,.acct-auth-card { border-width:2px; box-shadow:3px 3px 0 var(--ink-line); }
.acct-onboarding { background:#fff0bd; }
.acct-onboarding h2,.acct-auth-heading h2 { font-size:clamp(25px,6vw,32px); }
.acct-footer { margin-top:34px; padding-top:18px; border-top:1px solid var(--line); }

@keyframes acct-area-in { 0%,12%{opacity:.3;transform:scale(.84)} 25%,82%{opacity:.92;transform:scale(.94)} 100%{opacity:.3;transform:scale(.84)} }
@keyframes acct-word-find { 0%,12%{transform:scaleX(.12);opacity:.35} 35%,78%{transform:scaleX(1);opacity:1} 100%{transform:scaleX(.12);opacity:.35} }
@keyframes acct-pipe-turn { 0%,30%{transform:rotate(0)} 43%,82%{transform:rotate(90deg)} 100%{transform:rotate(0)} }
@keyframes acct-tap { 0%,25%,100%{transform:translateY(12px);opacity:0} 34%,55%{transform:translateY(0);opacity:1} 70%{opacity:0} }
@keyframes acct-water { 0%,43%{transform:scaleX(.05);opacity:.1} 67%,85%{transform:scaleX(1);opacity:1} 100%{opacity:.1} }
@keyframes acct-number-pop { 0%,18%,100%{opacity:0;transform:translate(-50%,-50%) scale(.65)} 32%,76%{opacity:1;transform:translate(-50%,-50%) scale(1)} }
@keyframes acct-bob { 50%{transform:translateY(-6px)} }

@media (min-width: 760px) {
  .acct-topbar { margin-bottom:20px; }
  .acct-mini-brand b { font-size:17px; }
  .acct-top-actions a { padding-inline:18px; font-size:13px; }
  .acct-marketing.acct-hero { min-height:610px; grid-template-columns:minmax(0,1fr) minmax(390px,.9fr); align-items:center; gap:28px; padding:48px 44px 0; }
  .acct-hero-visual { min-height:510px; align-self:end; }
  .acct-phone { width:298px; min-height:444px; padding:24px 18px; bottom:-27px; }
  .acct-phone-top { margin-top:7px; font-size:13px; }
  .acct-hero-otong { right:-5px; width:144px; }
  .acct-floating-cover { width:115px; }
  .acct-floating-cover.one { left:-2px; bottom:82px; }.acct-floating-cover.two { right:-4px; top:50px; }
  .acct-hero-text > h1 { font-size:clamp(58px,6vw,78px); }
  .acct-hero-copy { font-size:18px; }
  .acct-hero-proof b { font-size:23px; }.acct-hero-proof span { font-size:12px; }
  .acct-showcase,.acct-variety,.acct-fit { margin-top:94px; }
  .acct-motion-rail { grid-auto-flow:initial; grid-template-columns:repeat(4,minmax(0,1fr)); margin:0; padding:4px 0 16px; overflow:visible; }
  .acct-motion-stage { height:235px; }
  .acct-cover-rail { justify-content:center; overflow:visible; padding-inline:28px; }
  .acct-cover-rail figure,.acct-cover-rail img { width:130px; }
  .acct-cover-rail img { height:130px; }
  .acct-fit-grid { grid-template-columns:repeat(3,minmax(0,1fr)); }
  .acct-try-strip { min-height:250px; flex-direction:row; align-items:center; padding:40px 270px 40px 46px; }
  .acct-try-strip > img { width:265px; right:10px; }
  .acct-try-strip h2 { font-size:40px; }.acct-try-strip a { margin-left:auto; }
}
@media (max-width: 420px) {
  .acct-page { padding-left:12px; padding-right:12px; }
  .acct-mini-brand img { width:38px; height:38px; }.acct-mini-brand b { font-size:12.5px; }.acct-mini-brand small { font-size:7.8px; }
  .acct-top-actions a { padding-inline:9px; }.acct-top-actions a.primary { padding-inline:11px; }
  .acct-marketing.acct-hero { padding-left:17px; padding-right:17px; }
  .acct-hero-text > h1 { font-size:clamp(39px,11.8vw,49px); }
  .acct-hero-copy { font-size:15px; }
  .acct-hero-actions .acct-demo-cta { width:auto; min-width:176px; }
  .acct-hero-proof li { padding-inline:10px; }
  .acct-motion-rail { margin-left:-12px; margin-right:-12px; padding-left:12px; padding-right:12px; }
  .acct-try-strip { padding-right:120px; }.acct-try-strip > img { width:153px; right:-34px; }
}

/* ---------- kid picker ---------- */
.kid-list { display: flex; flex-direction: column; gap: 12px; margin-bottom: 16px; }
.kid-card {
  display: flex; align-items: center; gap: 14px;
  background: var(--surface); border: none; border-radius: var(--r-lg);
  padding: 16px; box-shadow: var(--shadow); cursor: pointer;
  font: inherit; text-align: left; width: 100%;
}
.kid-card:active { transform: scale(.97); }
.kid-face {
  width: 54px; height: 54px; flex: none; border-radius: 16px;
  background: var(--bg-soft); display: flex; align-items: center;
  justify-content: center; font-size: 28px;
}
.kid-name { font-weight: 800; font-size: 16px; }
.kid-meta { font-size: 12px; color: var(--ink-soft); font-weight: 700; margin-top: 2px; }

/* ---------- nickname builder ---------- */
.nk-hint {
  font-size: 12px; font-weight: 800; letter-spacing: .5px; text-transform: uppercase;
  color: var(--ink-soft); margin: 6px 0 10px;
}
/* four across, not five: the swatches now hold a whole character rather than a
   single emoji, and eight of them divide evenly into two tidy rows */
.nk-avatars {
  display: grid; grid-template-columns: repeat(6, 1fr); gap: 8px; margin-bottom: 22px;
}
.nk-av {
  aspect-ratio: 1; border: var(--border); border-radius: 14px;
  background: var(--surface); box-shadow: var(--shadow);
  cursor: pointer; padding: 4px;
  display: grid; place-items: center;
  transition: transform .1s ease, box-shadow .1s ease;
}
.nk-av img { width: 100%; height: 100%; object-fit: contain; display: block; }
.nk-av.on {
  border-color: var(--c1);
  transform: translate(2px, 2px);
  box-shadow: 1px 1px 0 var(--ink-line);
  background: var(--bg-soft);
}
.nk-poses {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 22px;
}
.nk-pose {
  min-width: 0; padding: 5px 4px;
  border: var(--border); border-radius: 14px;
  background: var(--surface); box-shadow: var(--shadow);
  cursor: pointer; font: inherit; color: var(--ink);
  transition: transform .1s ease, box-shadow .1s ease;
}
.nk-pose img { display: block; width: 100%; height: 92px; object-fit: contain; }
.nk-pose.on {
  border-color: var(--c1); transform: translate(2px, 2px);
  box-shadow: 1px 1px 0 var(--ink-line); background: var(--bg-soft);
}
.nk-namebox {
  display: flex; align-items: center; gap: 6px;
  background: var(--surface); border-radius: var(--r-md);
  padding: 14px 8px; box-shadow: var(--shadow);
}
.nk-name { flex: 1; font-weight: 800; font-size: 20px; }
.nk-arrow {
  width: 38px; height: 38px; flex: none; border: none; border-radius: 12px;
  background: var(--bg-soft); font: inherit; font-size: 20px; font-weight: 800;
  color: var(--ink); cursor: pointer;
}
.nk-arrow:active { transform: scale(.9); }
.nk-row {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  margin-top: 8px;
}
.nk-sub { font-size: 12px; font-weight: 700; color: var(--ink-soft); }
.nk-note {
  font-size: 11.5px; color: var(--ink-soft); line-height: 1.5;
  margin: 14px 0 4px; text-align: center;
}
.nk-badges-section {
  margin: 22px 0 18px; padding: 14px; border: 2px solid #ddcdb7;
  border-radius: 18px; background: #fffaf1;
}
.nk-badges-help { margin: -3px 0 5px; color: var(--ink-soft); font-size: 11px; line-height: 1.45; }
.nk-badges-note { min-height: 17px; margin: 7px 0 10px; color: var(--c1); font-size: 10.5px; font-weight: 900; }
.nk-badges-grid {
  display: grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap: 8px;
  max-height: 248px; overflow-y: auto; padding: 3px;
}
.nk-badge-choice {
  position: relative; min-width: 0; aspect-ratio: 1; display: grid; place-items: center;
  padding: 7px; border: 2px solid #ddcdb7; border-radius: 15px;
  background: #fff; box-shadow: 0 3px 0 #d8c3a8; font: inherit; cursor: pointer;
}
.nk-badge-choice > img { width: 100%; height: 100%; object-fit: contain; display: block; }
.nk-badge-choice > span {
  position: absolute; left: 3px; right: 3px; bottom: 3px; padding: 2px 3px;
  border-radius: 7px; background: rgba(255,253,248,.9); font-size: 7px;
  font-weight: 900; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.nk-badge-choice > i {
  position: absolute; z-index: 3; right: -4px; top: -5px; width: 20px; height: 20px;
  display: grid; place-items: center; border-radius: 50%; background: #276e66;
  color: #fff; border: 2px solid #fff; font-style: normal; font-size: 9px; font-weight: 1000;
}
.nk-badge-choice.on { border-color: #c8912f; box-shadow: 0 0 0 2px #f2d88b,0 3px 0 #b98023; }
.nk-badge-choice.badge-art-mastery { --badge-medal-pad: 5px; border-radius: 50%; }
.nk-badge-choice.badge-art-mastery > img { border-radius: 50%; object-fit: cover; }

/* ---------- leaderboard ---------- */
#screen-leader .scroll-area {
  /* The page chrome stays still. Only the Top 50 viewport scrolls, which lets
     an out-of-Top-50 player's separator + row remain pinned underneath it. */
  display: flex; flex-direction: column; min-height: 0; overflow: hidden;
}
#screen-leader .lead-head,
#screen-leader .store-note,
#screen-leader .lead-explain,
#screen-leader .lead-tabs { flex: none; }
.lead-tabs {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px;
  margin: 2px 0 10px; padding: 4px;
  border: 2px solid var(--ink-line); border-radius: var(--r-md);
  background: var(--bg-soft);
}
.lead-tab {
  min-height: 44px; padding: 8px 10px; border: 0; border-radius: 10px;
  background: transparent; color: var(--ink-soft); font: inherit;
  font-size: 12.5px; font-weight: 900; cursor: pointer;
}
.lead-tab.on { background: var(--c1); color: #fff; box-shadow: 0 2px 0 rgba(47,42,38,.25); }
.lead-tab:focus-visible { outline: 3px solid var(--star); outline-offset: 2px; }
.lead-explain { align-self: flex-start; max-width: 100%; min-height: 36px; padding: 2px 0 5px; margin: 0 0 3px; border: 0; background: transparent; color: var(--c1-dark, #276e66); font: inherit; font-size: 12px; font-weight: 800; text-align: left; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.lead-explain[hidden] { display: none; }
.lead-explain:focus-visible { outline: 3px solid var(--star); border-radius: 6px; }
.lead-retry { display: block; margin: 12px auto 0; }
.league-info-card { max-width: 520px; max-height: 88dvh; overflow-y: auto; overscroll-behavior: contain; text-align: left; line-height: 1.6; }
.league-info-card h3 { padding-right: 34px; text-align: left; }
.league-info-card h4 { margin: 22px 0 8px; font-size: 16px; }
.league-info-card p, .league-info-card li { font-size: 14px; overflow-wrap: anywhere; }
.league-info-card ul { padding-left: 21px; }
.league-info-card p { margin: 10px 0; }
.league-info-card .modal-x { position: sticky; top: 0; float: right; z-index: 1; background: var(--surface); }
.league-info-preview { background: #fff2c2; padding: 12px; border-radius: 12px; }
.league-info-total { margin: 18px 0; padding: 16px; border-radius: 14px; background: #e2efe9; text-align: center; color: #276e66; }
.league-info-footnote { color: var(--ink-soft); }
.lead-you { display: inline-block; padding: 1px 5px; border-radius: 5px; background: #276e66; color: white; font-size: 9px; vertical-align: middle; }
.lead-list {
  display: flex; flex-direction: column; gap: 8px;
  /* Fill whatever height this phone actually has. When lead-mine is empty
     (the player is already Top 50), the list gets all remaining space. When
     it contains a personal row, flex automatically reserves exactly that
     row's height below and gives the rest to the scrolling Top 50. */
  flex: 1 1 auto; min-height: 0; height: auto;
  overflow-y: auto; overscroll-behavior: contain;
  padding: 3px 4px 8px 2px; scrollbar-width: thin;
}
.lead-row {
  display: flex; align-items: center; gap: 12px; flex: none;
  background: var(--surface); border-radius: var(--r-md);
  padding: 11px 14px; box-shadow: var(--shadow); cursor:pointer;
}
.lead-row:focus-visible { outline:3px solid var(--star); outline-offset:2px; }
.lead-row.me { background: #e2efe9; box-shadow: 0 0 0 2px var(--c1); }
.lead-row.rank-1 {
  background:
    radial-gradient(circle at 12% 18%, rgba(255,255,255,.9), transparent 18%),
    linear-gradient(115deg, #fff7c7 0%, #f7d979 38%, #fff2ad 60%, #e9b84b 100%);
  border: 1px solid rgba(190,133,32,.65);
  box-shadow: 0 0 0 2px rgba(255,221,111,.42), 0 4px 16px rgba(184,128,25,.26);
}
.lead-row.rank-2 {
  background:
    radial-gradient(circle at 12% 18%, rgba(255,255,255,.92), transparent 18%),
    linear-gradient(115deg, #f5f9fc 0%, #c1ccd4 38%, #ffffff 60%, #aab7c0 100%);
  border: 1px solid rgba(108,125,138,.58);
  box-shadow: 0 0 0 2px rgba(205,218,227,.65), 0 4px 14px rgba(112,132,145,.22);
}
.lead-row.rank-3 {
  background:
    radial-gradient(circle at 12% 18%, rgba(255,245,231,.9), transparent 18%),
    linear-gradient(115deg, #f7d4b2 0%, #c17b52 38%, #ffe4c5 60%, #a85e3b 100%);
  border: 1px solid rgba(128,66,39,.58);
  box-shadow: 0 0 0 2px rgba(231,169,128,.55), 0 4px 14px rgba(147,76,42,.22);
}
/* Podium cards use brighter backgrounds, so their identity text stays
   readable instead of inheriting the light-on-surface default. */
.lead-row.rank-1 .lead-name,
.lead-row.rank-1 .lead-sub,
.lead-row.rank-2 .lead-name,
.lead-row.rank-2 .lead-sub,
.lead-row.rank-3 .lead-name,
.lead-row.rank-3 .lead-sub {
  color: #111111;
}
.lead-rank {
  width: 30px; flex: none; font-weight: 800; font-size: 14px;
  color: var(--ink-soft); text-align: center;
}
.lead-row:nth-child(1) .lead-rank { color: var(--star); font-size: 17px; }
/* ---------- weekly league ---------- */
.lead-head { margin: 2px 0 3px; }
.lg-top-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
}
.lg-tier {
  font-size: 18px; font-weight: 900; color: var(--tier, var(--ink));
  display: flex; align-items: center; gap: 6px;
}
.lg-tier::before {
  content: ''; width: 12px; height: 12px; border-radius: 50%;
  background: var(--tier, var(--line)); border: 2px solid var(--ink-line);
}
.lg-week { font-size: 11.5px; font-weight: 800; color: var(--ink-soft); }
/* the explainer block: your level range, what's above you, and where you
   stand lifetime — added so the board answers "am I doing okay" without
   making the player go compute it from a level number themselves */
.lg-info {
  display: flex; flex-direction: column; gap: 2px;
  font-size: 11.5px; color: var(--ink-soft); margin-top: 6px;
}
.lg-next.lg-top { color: var(--star); font-weight: 800; }
.lg-xprank {
  font-size: 12px; font-weight: 800; color: var(--c1); margin-top: 6px;
}

/* the break between the leaders and your own neighbourhood */
.lead-gap {
  text-align: center; color: var(--ink-soft);
  font-size: 18px; letter-spacing: 4px; padding: 2px 0 6px;
}
.lead-mine { flex: none; margin-top: 4px; }
.lead-mine:empty { display: none; }
.lead-rank.crowned { font-size: 20px; }

.lead-face { font-size: 22px; flex: none; }

/* League cosmetic frames — a ring around the avatar photo, not the row. Tier
   rings use the same three colours as the league board itself (see league.js
   TIERS); rank rings are a shade louder and get a small medal badge, since
   holding #1 in your tier should read as more than just "still gold". Uses
   box-shadow rather than border so it never nudges the image's own layout
   box — a ring drawn OUTSIDE the element's box, not added to it. */
.otong-frame {
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%; line-height: 0; position: relative;
}
/* AN EMOJI AVATAR HAS NO HEIGHT OF ITS OWN. The ring was written for the
   Otong image, which .lead-face sizes to 30x30, so the circle came out right.
   A player using an emoji renders a bare <span> inside a frame with
   line-height:0 — zero height, so the "ring" collapsed into a flat bar behind
   the emoji. That is what 2nd and 3rd place were showing. Giving the frame its
   own box makes it a circle whatever is inside it. */
.lead-face .otong-frame {
  width: 30px; height: 30px; line-height: 1; font-size: 18px;
}
.otong-frame-bronze { box-shadow: 0 0 0 2px #b3743a; }
.otong-frame-silver { box-shadow: 0 0 0 2px #9aa4ad; }
.otong-frame-gold   { box-shadow: 0 0 0 2px #d9a441; }
.otong-frame-rank1, .otong-frame-rank2, .otong-frame-rank3 { box-shadow: 0 0 0 3px; }
.otong-frame-rank1 {
  padding: 3px;
  background:
    radial-gradient(circle at 28% 18%, #fffdf0 0 7%, transparent 24%),
    conic-gradient(from 20deg, #fff5a6, #d89c2f, #fff8c9, #e4ad3e, #fff5a6);
  box-shadow: 0 0 0 2px #b67b20, 0 0 7px rgba(255,213,77,.95), 0 0 16px rgba(255,192,48,.5);
}
.otong-frame-rank2 {
  padding: 3px;
  background:
    radial-gradient(circle at 28% 18%, #ffffff 0 7%, transparent 24%),
    conic-gradient(from 25deg, #f7fbff, #91a0ad, #ffffff, #c4cdd4, #f7fbff);
  box-shadow: 0 0 0 2px #74818b, 0 0 8px rgba(176,193,204,.82), 0 0 14px rgba(146,164,177,.4);
}
.otong-frame-rank3 {
  padding: 3px;
  background:
    radial-gradient(circle at 28% 18%, #fff4e9 0 7%, transparent 24%),
    conic-gradient(from 25deg, #f1c19a, #9d5735, #ffe0b8, #c0784d, #f1c19a);
  box-shadow: 0 0 0 2px #824328, 0 0 8px rgba(190,113,70,.78), 0 0 14px rgba(169,91,51,.38);
}
/* NO corner medal on the avatar. The rank column at the left of every row
   already shows 🥇🥈🥉, so a second copy tucked into the ring said the same
   thing twice — and the coloured ring alone already reads as the podium. */
/* Rank 1 wears a crown. This is the ONLY crown in the app — the leaderboard
   row deliberately draws none of its own, and cosmetics (which once included a
   buyable gold crown) are gone, so 👑 now has exactly one meaning: holding
   first place right now. */
.otong-frame-rank1::before {
  content: '👑'; position: absolute; top: -13px; left: 50%;
  transform: translateX(-50%) rotate(-6deg); font-size: 15px; line-height: 1;
}

/* Cosmetic accessories (hats, crowns) sit ABOVE the body image, mostly
   outside its own box — Otong's head already touches the top edge of his own
   384x384 canvas with zero headroom, so there is nowhere to put a hat INSIDE
   it. .otong-wrap shrink-wraps to exactly the body <img>'s rendered size and
   allows overflow, so the accessory (sized and positioned as a % of that box)
   scales correctly whether the avatar is rendered at 16px or 92px. */
.otong-wrap { position: relative; display: inline-flex; overflow: visible; }
.acc-img {
  position: absolute; left: 50%; transform: translateX(-50%);
  pointer-events: none; display: block;
}

/* Otong now stands in for the old emoji avatar in five different places, each
   with its own box. One rule sizes him to whatever container he lands in, so a
   new avatar site never needs its own image CSS. */
.kid-face img, .lead-face img, .wc-face img,
#ci-face img, #btn-profile img {
  width: 1.35em; height: 1.35em;
  object-fit: contain; display: block;
}
#btn-profile img { width: 30px; height: 30px; margin: 0 auto; }
.lead-face img { width: 30px; height: 30px; }
.lead-name { flex: 1; font-weight: 800; font-size: 14px; display:flex; align-items:center; gap:4px; flex-wrap:wrap; }
.lead-main-badge { width:23px; height:23px; flex:none; display:inline-grid; place-items:center; margin-left:1px; }
.lead-main-badge img { width:100%; height:100%; object-fit:contain; display:block; filter:drop-shadow(0 2px 2px rgba(47,42,38,.22)); }
.lead-main-badge.badge-art-mastery { --badge-medal-pad:2px; box-shadow:inset 0 0 0 1px rgba(255,248,221,.82),0 1px 2px rgba(47,42,38,.25); }
.lead-main-badge.badge-art-mastery::after { box-shadow:inset 0 0 0 1px rgba(255,243,180,.9); }
.lead-stars { font-weight: 800; font-size: 13px; color: var(--c1); }
.lead-empty { text-align: center; color: var(--ink-soft); font-size: 13px; padding: 30px 0; }

.nk-city {
  width: 100%; padding: 13px 14px;
  border: 2px solid var(--line); border-radius: var(--r-md);
  background: var(--surface); color: var(--ink);
  font: inherit; font-weight: 700; font-size: 15px;
}
.lead-body { flex: 1; min-width: 0; }
.lead-sub { font-size: 11px; color: var(--ink-soft); font-weight: 700; margin-top: 1px; }
.lead-ig { font-weight: 700; font-size: 11.5px; color: var(--c2); }

/* Compact public player card. It exposes only the same nickname, avatar,
   location and rank already visible on the leaderboard plus three badges. */
.player-card-modal { max-width:380px; text-align:left; overflow:visible; }
.player-card-top { display:flex; align-items:center; gap:14px; padding:5px 30px 14px 2px; }
.player-card-face {
  width:64px; height:64px; flex:none; display:grid; place-items:center; border-radius:50%;
  background:#e4f0ec; border:3px solid #3f7d74; box-shadow:0 4px 0 rgba(47,42,38,.2);
}
.player-card-face img { width:52px; height:52px; object-fit:contain; }
.player-card-top h3 { margin:0; font-size:20px; font-weight:900; overflow-wrap:anywhere; }
.player-card-top p,.player-card-meta { margin:3px 0 0; color:var(--ink-soft); font-size:12px; font-weight:800; }
.player-card-meta { margin:-8px 0 13px 80px; }
.player-card-badges { display:grid; grid-template-columns:repeat(3,1fr); gap:8px; padding-top:13px; border-top:2px solid #eadfce; }
.player-card-badges > div { min-width:0; text-align:center; }
.player-badge-art { width:66px; height:66px; max-width:100%; display:grid; place-items:center; margin:0 auto 5px; }
.player-badge-art.badge-art-mastery { --badge-medal-pad:5px; }
.player-badge-art img { width:100%; height:100%; max-width:100%; object-fit:contain; display:block; }
.player-card-badges b { display:block; font-size:9.5px; line-height:1.25; overflow-wrap:anywhere; }
.player-card-badges > p { grid-column:1/-1; margin:8px 0; text-align:center; color:var(--ink-soft); font-size:12px; }
.wx-badge { display:flex; align-items:center; justify-content:center; gap:5px; margin-top:6px; }
.wx-badge-art { width:25px; height:25px; object-fit:contain; }


/* ---------- game icons ---------------------------------------------------
   The <symbol>s carry their own colours, so these rules only size them. The
   emoji fallback keeps the same class, hence the two selectors.            */
.gc-emoji-svg { width: 46px; height: 46px; display: block; }
.sr-glyph { width: 30px; height: 30px; display: block; }
.sr-icon { display: grid; place-items: center; }


/* ---------- home app bar on a phone --------------------------------------
   Six 42px buttons plus a title do not fit across 375px, so the last one was
   sliding off the right edge. Rather than shrinking every target below what a
   child can reliably hit, the home bar wraps: title on its own line, actions
   centred underneath. Only the home bar needs this — every other screen has a
   back button, a title, and nothing else.                                   */
@media (max-width: 480px) {
  #screen-home .app-bar { flex-wrap: wrap; row-gap: 6px; }
  #screen-home .app-bar-title { flex: 1 0 100%; justify-content: flex-start; }
  /* Right-aligned, not centred: the wordmark above starts hard left, so a
     centred row of buttons lined up with neither edge. */
  #screen-home .app-bar-actions { flex: 1 0 100%; justify-content: flex-end; }
}


/* ---------- wordmark ------------------------------------------------------
   The credit sits under the name rather than beside it, so it reads as a
   signature and never competes with the title for width on a phone.        */
.gate-by {
  margin: -2px 0 6px; text-align: center;
  font-size: 13px; font-weight: 700; letter-spacing: .3px;
  color: var(--ink-soft); opacity: .8;
}
.bar-name { display: flex; flex-direction: column; line-height: 1.05; }
.bar-by {
  font-size: 10px; font-weight: 700; letter-spacing: .4px;
  color: var(--ink-soft); opacity: .75;
}


/* Three controls per kid card: ✎ edit, ↺ reset progress, 🗑 delete. Sized to
   a comfortable tap target (36px) rather than the 28px they started at —
   these sit close together and two of the three are destructive, so a
   mis-tap is expensive. Ordered least to most destructive, left to right. */
.kid-card { position: relative; }
.kid-wipe, .kid-edit, .kid-del {
  position: absolute; top: 6px;
  width: 36px; height: 36px; display: grid; place-items: center;
  border-radius: 50%; font-size: 18px; line-height: 1;
  color: var(--ink-soft); opacity: .6;
}
.kid-del  { right: 8px; }
.kid-wipe { right: 48px; }
.kid-edit { right: 88px; }
.kid-wipe:active, .kid-edit:active, .kid-del:active {
  opacity: 1; transform: scale(.9); background: var(--bg-soft);
}

/* the free-text alternative under the word picker — same boxed shape as the
   word picker above it, so it reads as an equal option, not an afterthought */
.nk-prefix { font-weight: 800; opacity: .7; margin-right: 2px; }
.nk-or {
  text-align: center; font-size: 12px; opacity: .55; margin: 10px 0 6px;
}
.nk-custom-input {
  flex: 1; border: none; background: transparent; font: inherit;
  font-weight: 800; font-size: 20px; color: var(--ink); min-width: 0;
}
.nk-custom-input:focus { outline: none; }

.nk-toggle {
  display: flex; align-items: center; gap: 8px;
  margin: 10px 2px 0; font-size: 13px; font-weight: 700; color: var(--ink-soft);
}
.nk-toggle input { width: 18px; height: 18px; accent-color: var(--c1); }


/* ==========================================================================
   Paket A/B — Tebak Emoji, Acak Huruf, Urutan Pola, Rotasi Bentuk,
   Bayangan Cermin, Jaring Kubus, Puzzle Potong
   Shared "multiple choice" building blocks: .right / .wrong / .ruled-out
   are reused across Emoji, Rotasi, and Jaring Kubus so picking a correct
   answer, a wrong one, or a hint-eliminated one always look the same.
   ========================================================================== */
.right { outline: 3px solid var(--good); background: #d9ebe5 !important; }
.wrong { outline: 3px solid var(--warn); background: #f7e3d1 !important; }
.ruled-out { opacity: .3; text-decoration: line-through; }

/* ---------- tebak emoji ---------- */
.em-clue { font-size: 52px; text-align: center; margin: 10px 0 26px; line-height: 1.3; }
.em-opts { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.em-opt {
  padding: 16px 8px; border: none; border-radius: var(--r-md);
  background: var(--surface); box-shadow: var(--shadow);
  font: inherit; font-weight: 800; font-size: 14px; color: var(--ink); cursor: pointer;
}
.em-opt:active { transform: scale(.96); }
.em-opt:disabled { cursor: default; }

/* type-in mode: intermediate and up spell the answer instead of picking it */
.em-scaffold {
  text-align: center; font-weight: 800; font-size: 22px; letter-spacing: 6px;
  color: var(--ink-soft); margin-bottom: 18px;
}
.em-answer-wrap { display: flex; gap: 10px; align-items: center; }
.em-answer-input { flex: 1; margin: 0; }

/* ---------- acak huruf ---------- */
.an-clue {
  text-align: center; font-size: 13px; color: var(--ink-soft); font-weight: 700;
  margin-bottom: 18px;
}
.an-clue b { color: var(--c3); font-size: 15px; }
.an-tiles { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-bottom: 24px; }
.an-tile {
  width: 2.1em; height: 2.1em;
  border: none; border-radius: var(--r-md);
  background: var(--surface); box-shadow: var(--shadow);
  font: inherit; font-weight: 800; color: var(--ink); cursor: pointer;
}
.an-tile:active { transform: scale(.92); }
.an-tile.sel { outline: 3px solid var(--c3); transform: scale(1.06); }
.an-tiles.ok .an-tile { background: #d9ebe5; color: #4f8578; }
.an-check { display: block; margin: 0 auto; }

/* ---------- urutan pola ---------- */
.pt-row { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin: 18px 0 26px; }
.pt-chip {
  min-width: 2.4em; height: 2.4em; padding: 0 8px;
  display: flex; align-items: center; justify-content: center;
  background: var(--surface); box-shadow: var(--shadow); border-radius: var(--r-md);
  font-weight: 800; font-size: 20px; color: var(--ink);
}
.pt-chip.blank { border: 2px dashed var(--c4); background: rgba(255,253,249,.7); color: var(--ink-soft); }
.pt-chip.blank.typing { border-style: solid; border-color: var(--c4); color: var(--ink); }
.pt-chip.blank.ok { background: #d9ebe5; border-color: var(--good); color: #4f8578; }
.pt-chip.blank.shake { animation: shake .38s ease; }

/* ---------- rotasi bentuk ---------- */
.rt-target-wrap { display: flex; flex-direction: column; align-items: center; gap: 8px; margin-bottom: 22px; }
.rt-deg { font-weight: 800; font-size: 15px; color: var(--c1); }
.rt-opts { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.rt-opt {
  border: none; border-radius: var(--r-md); padding: 10px; min-width: 0;
  background: var(--surface); box-shadow: var(--shadow); cursor: pointer;
}
.rt-opt:active { transform: scale(.96); }
.rt-opt:disabled { cursor: default; }
.rt-grid { display: grid; gap: 3px; width: 100px; height: 100px; max-width: 100%; margin: 0 auto; }
.rt-target-grid { width: 96px; height: 96px; }
.rt-cell { background: rgba(255,253,249,.6); border: 1px solid var(--line); border-radius: 3px; }
.rt-cell.filled { background: var(--c1); border-color: var(--c1); }

/* ---------- bayangan cermin ---------- */
.mr-axis {
  text-align: center; font-weight: 800; font-size: 13px; color: var(--c2);
  margin-bottom: 14px; text-transform: uppercase; letter-spacing: .4px;
}
.mr-grid { display: grid; gap: 3px; margin: 0 auto 20px; width: min(100%, 320px); aspect-ratio: 1; }
.mr-cell { border: 1px solid var(--line); border-radius: 3px; background: rgba(255,253,249,.5); }
.mr-cell.given.filled { background: var(--c2); border-color: var(--c2); }
.mr-cell.blank { background: rgba(255,253,249,.85); cursor: pointer; }
.mr-cell.blank.filled { background: var(--c8); border-color: var(--c8); }
.mr-cell.blank.hinted { outline: 2px dashed var(--star); }
.mr-grid.ok .mr-cell.blank.filled { background: var(--good); border-color: var(--good); }
.mr-grid.shake { animation: shake .38s ease; }
/* the mirror line itself, so the axis is never just implied by a label */
.mr-grid.mr-axis-v { border-left: 3px solid var(--c2); padding-left: 2px; }
.mr-grid.mr-axis-h { border-top: 3px solid var(--c2); padding-top: 2px; }

/* ---------- jaring kubus: clarity preview ---------- */
.cn-question-card {
  text-align: center; margin: 2px auto 16px; padding: 14px 16px;
  max-width: 520px; border: 2px solid var(--line); border-radius: var(--r-md);
  background: color-mix(in srgb, var(--c3) 11%, var(--surface));
}
.cn-question-card h3 { margin: 4px 0 10px; line-height: 1.55; font-size: clamp(16px, 4vw, 20px); }
.cn-kicker { color: var(--c3); font-size: 11px; font-weight: 900; letter-spacing: 1.2px; }
.cn-net-wrap { display: flex; justify-content: center; margin: 8px 0 22px; padding: 10px 0 18px; }
.cn-net {
  display: grid; grid-template-columns: repeat(4, clamp(50px, 15vw, 70px));
  grid-template-rows: repeat(3, clamp(50px, 15vw, 70px)); gap: 5px;
}
.cn-sq { position: relative; border-radius: 8px; box-shadow: var(--shadow); }
.cn-sq.reference { outline: 4px solid var(--ink); outline-offset: 2px; z-index: 2; }
.cn-face {
  position: relative; display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%; min-width: 44px; min-height: 44px;
  border: 2px solid color-mix(in srgb, var(--face) 65%, #332b25);
  border-radius: 8px; background: var(--face); color: #332b25;
}
.cn-symbol { font-size: clamp(20px, 7vw, 34px); font-weight: 900; line-height: 1; text-shadow: 0 1px rgba(255,255,255,.45); }
.cn-face-tag {
  position: absolute; left: 50%; transform: translateX(-50%); z-index: 3;
  white-space: nowrap; border: 2px solid var(--ink); border-radius: 999px;
  background: var(--ink); color: #fff; font-size: 8px; font-weight: 900;
  letter-spacing: .5px; line-height: 1; padding: 4px 6px;
}
.cn-face-tag { top: -14px; }
.cn-question-face { width: 58px; height: 58px; margin: 8px auto 0; }
.cn-inline-face { display: inline-flex; width: 34px; height: 34px; min-width: 34px; min-height: 34px; vertical-align: middle; margin: 0 3px; }
.cn-inline-face .cn-symbol { font-size: 18px; }
.cn-opts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.cn-opt {
  min-height: 86px; border: 2px solid var(--line); border-radius: var(--r-md); padding: 10px;
  background: var(--surface); box-shadow: var(--shadow); cursor: pointer;
  color: var(--ink); font: inherit; font-weight: 800;
}
.cn-opt:active { transform: scale(.96); }
.cn-opt:disabled { cursor: default; }
.cn-opt.right { outline: 4px solid var(--good); }
.cn-option-face { width: 54px; height: 54px; margin: 0 auto 6px; }
.cn-color-name { display: block; font-size: 12px; }
.cn-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.cn-pair > span { display: grid; gap: 5px; font-size: 9px; letter-spacing: .4px; }
.cn-pair .cn-option-face { width: 46px; height: 46px; min-width: 46px; min-height: 46px; margin: 0 auto; }
@media (max-width: 390px) {
  .cn-question-card { padding: 11px 10px; }
  .cn-net { gap: 4px; }
  .cn-opt { min-height: 78px; padding: 8px; }
}

/* ---------- puzzle potong ---------- */
.tg-board {
  display: grid; gap: 3px; margin: 0 auto 18px; width: min(100%, 300px);
  /* aspect-ratio is set inline per level to match the silhouette's shape */
}
.tg-cell { border-radius: 3px; }
.tg-cell.inside {
  border: 2px dashed var(--line); background: rgba(255,253,249,.5); cursor: pointer;
}
.tg-cell.inside.filled { border-style: solid; }
.tg-board.ok .tg-cell.inside { border-color: var(--good); }
.tg-board.shake { animation: shake .38s ease; }
.tg-tray {
  display: flex; gap: 10px; flex-wrap: wrap; justify-content: center;
  padding-top: 6px; border-top: 2px dashed var(--line);
}
.tg-piece {
  border: none; border-radius: var(--r-sm); padding: 6px;
  background: var(--surface); box-shadow: var(--shadow); cursor: pointer;
}
.tg-piece.sel { outline: 3px solid var(--c4); transform: scale(1.06); }
.tg-mini { display: grid; gap: 2px; width: 52px; height: 52px; }
.tg-mc { border-radius: 3px; }


/* ==========================================================================
   Paket C/D — Jalan Bayangan, Tirukan Nada, Ingat Tempatnya
   ========================================================================== */

/* ---------- jalan bayangan ----------
   Two mazes have to sit side by side even on the narrowest phone, so the pair
   is a 2-column grid of equal fractions and each maze scales to its column
   rather than to a fixed pixel size. */
.sm-pair {
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
  width: 100%; margin-bottom: 12px;
}
.sm-side { min-width: 0; }
.sm-label {
  text-align: center; font-size: 11px; font-weight: 800; letter-spacing: .4px;
  text-transform: uppercase; color: var(--c5); margin-bottom: 5px;
}
.sm-label-b { color: var(--ink-soft); }
.sm-grid { display: grid; width: 100%; aspect-ratio: 1; background: var(--surface); border-radius: var(--r-sm); overflow: hidden; }
.sm-grid-b { opacity: .93; }
.sm-cell { position: relative; background: transparent; }
/* walls are drawn as insets so neighbouring cells share one crisp line */
.sm-cell.wn { box-shadow: inset 0 2px 0 var(--ink); }
.sm-cell.we { box-shadow: inset -2px 0 0 var(--ink); }
.sm-cell.ws { box-shadow: inset 0 -2px 0 var(--ink); }
.sm-cell.ww { box-shadow: inset 2px 0 0 var(--ink); }
.sm-cell.wn.we { box-shadow: inset 0 2px 0 var(--ink), inset -2px 0 0 var(--ink); }
.sm-cell.wn.ws { box-shadow: inset 0 2px 0 var(--ink), inset 0 -2px 0 var(--ink); }
.sm-cell.wn.ww { box-shadow: inset 0 2px 0 var(--ink), inset 2px 0 0 var(--ink); }
.sm-cell.we.ws { box-shadow: inset -2px 0 0 var(--ink), inset 0 -2px 0 var(--ink); }
.sm-cell.we.ww { box-shadow: inset -2px 0 0 var(--ink), inset 2px 0 0 var(--ink); }
.sm-cell.ws.ww { box-shadow: inset 0 -2px 0 var(--ink), inset 2px 0 0 var(--ink); }
.sm-cell.wn.we.ws { box-shadow: inset 0 2px 0 var(--ink), inset -2px 0 0 var(--ink), inset 0 -2px 0 var(--ink); }
.sm-cell.wn.we.ww { box-shadow: inset 0 2px 0 var(--ink), inset -2px 0 0 var(--ink), inset 2px 0 0 var(--ink); }
.sm-cell.wn.ws.ww { box-shadow: inset 0 2px 0 var(--ink), inset 0 -2px 0 var(--ink), inset 2px 0 0 var(--ink); }
.sm-cell.we.ws.ww { box-shadow: inset -2px 0 0 var(--ink), inset 0 -2px 0 var(--ink), inset 2px 0 0 var(--ink); }
.sm-cell.wn.we.ws.ww { box-shadow: inset 0 2px 0 var(--ink), inset -2px 0 0 var(--ink), inset 0 -2px 0 var(--ink), inset 2px 0 0 var(--ink); }
.sm-cell.goal::after {
  content: '⚑'; position: absolute; inset: 0;
  display: grid; place-items: center; font-size: 13px; color: var(--warn);
}
.sm-cell.hero::before {
  content: ''; position: absolute; inset: 22%;
  border-radius: 50%; background: var(--c5); box-shadow: var(--shadow);
}
.sm-grid-b .sm-cell.hero::before { background: var(--ink-soft); }
.sm-cell.hero.home::before { background: var(--good); }
.sm-cell.flash { animation: smflash .5s ease 3; }
@keyframes smflash { 50% { background: var(--star); } }
.sm-hud { text-align: center; font-size: 12px; font-weight: 800; color: var(--ink-soft); margin-bottom: 10px; }
.sm-hud b, .sm-hud span { color: var(--ink); }
.sm-pad { display: flex; flex-direction: column; align-items: center; gap: 7px; }
.sm-arrow-row { display: flex; gap: 7px; }
.sm-arrow {
  width: 54px; height: 46px; border: none; border-radius: var(--r-md);
  background: var(--surface); box-shadow: var(--shadow);
  font-size: 19px; color: var(--ink); cursor: pointer;
}
.sm-arrow:active { transform: scale(.92); }

/* ---------- tirukan nada ---------- */
.si-hud { display: flex; justify-content: space-between; align-items: center; font-size: 12px; font-weight: 800; color: var(--ink-soft); }
.si-lives { letter-spacing: 2px; }
.si-status { text-align: center; font-weight: 800; font-size: 15px; color: var(--ink); margin: 14px 0 20px; min-height: 1.4em; }
.si-pads { display: grid; gap: 12px; margin: 0 auto; width: min(100%, 300px); }
.si-four { grid-template-columns: 1fr 1fr; }
.si-six  { grid-template-columns: repeat(3, 1fr); }
.si-pad {
  aspect-ratio: 1; border: none; border-radius: var(--r-md);
  box-shadow: var(--shadow); cursor: pointer; opacity: .55;
  transition: opacity .12s ease, transform .12s ease;
}
.si-pad.lit { opacity: 1; transform: scale(1.06); box-shadow: var(--shadow-lg); }
.si-pad:active { opacity: 1; transform: scale(.95); }
.si-pads.shake { animation: shake .38s ease; }

/* ---------- ingat tempatnya ---------- */
.rc-status { text-align: center; font-weight: 800; font-size: 15px; color: var(--ink); margin-bottom: 16px; min-height: 1.4em; }
.rc-grid { display: grid; gap: 8px; margin: 0 auto; width: min(100%, 320px); aspect-ratio: 1; }
.rc-cell {
  border: none; border-radius: var(--r-sm);
  background: var(--surface); box-shadow: var(--shadow);
  font-size: 26px; line-height: 1; cursor: pointer; padding: 0;
  display: grid; place-items: center;
}
/* the icon stays in the DOM and is only made invisible, so the recall phase
   cannot be beaten by reading the markup. `color: transparent` on the cell
   does nothing here — emoji are colour glyphs baked into the font, not text
   painted with the CSS `color` you set, so the icon stayed visible through
   the whole memorize phase no matter what color was applied to it. opacity
   on the icon's own inner span actually hides it, and only the icon: the
   cell's own background/border (and its clickability) are untouched. */
.rc-cell.hidden-item .rc-icon { opacity: 0; }
.rc-cell.got { background: #d9ebe5; }
.rc-cell.got .rc-icon { opacity: 1; }
.rc-cell.miss { background: #f7e3d1; opacity: .6; }
.rc-cell.flash { animation: smflash .4s ease 3; }
.rc-cell:active { transform: scale(.94); }


/* ==========================================================================
   Paket E/F — Sortir Warna, Detektif Mini, Teka-teki Zebra
   ========================================================================== */

/* ---------- sortir warna ---------- */
.ws-tubes {
  display: flex; flex-direction: column; gap: 14px;
  justify-content: center; align-items: center; padding-top: 10px;
}
.ws-tube-row { display: flex; justify-content: center; gap: 12px; }
.ws-tube {
  display: flex; flex-direction: column; gap: 3px;
  padding: 5px; border: none;
  background: var(--surface); box-shadow: var(--shadow);
  border-radius: 8px 8px 16px 16px; cursor: pointer;
}
.ws-tube.sel { outline: 3px solid var(--c8); transform: translateY(-8px); }
.ws-tube.flash { animation: smflash .5s ease 3; }
.ws-tube.shake { animation: shake .38s ease; }
.ws-slot {
  width: 28px; height: 28px; border-radius: 5px;
  background: rgba(230, 217, 198, .35);
}
.ws-slot.full { box-shadow: inset 0 -2px 0 rgba(0,0,0,.08); }
.ws-tubes.ok .ws-tube { outline: 2px solid var(--good); }

/* ---------- detektif & zebra: shared clue list and chips ---------- */
.dt-clues {
  background: var(--surface); border-radius: var(--r-md);
  box-shadow: var(--shadow); padding: 12px 14px; margin-bottom: 18px;
}
.dt-clue {
  font-size: 13px; line-height: 1.55; color: var(--ink);
  padding-left: 16px; position: relative; margin-bottom: 6px;
}
.dt-clue:last-child { margin-bottom: 0; }
.dt-clue::before {
  content: '•'; position: absolute; left: 3px; color: var(--c3); font-weight: 800;
}
.dt-chip {
  width: 2.2em; height: 2.2em; font-size: 22px; line-height: 1;
  border: none; border-radius: var(--r-sm);
  background: var(--surface); box-shadow: var(--shadow); cursor: pointer;
}
.dt-chip.sel { outline: 3px solid var(--c3); transform: scale(1.08); }
.dt-chip:active { transform: scale(.92); }

/* ---------- detektif mini ---------- */
.dt-houses {
  display: grid; gap: clamp(6px, 2vw, 10px);
  width: 100%; max-width: 520px; margin: 0 auto 20px;
}
.dt-house {
  min-height: clamp(82px, 23vw, 116px);
  border: 3px dashed var(--line); border-radius: var(--r-sm);
  background: rgba(255,253,249,.6); cursor: pointer;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
}
.dt-house.filled { border-style: solid; background: var(--surface); box-shadow: var(--shadow); }
.dt-house.hinted { border-color: var(--star); }
.dt-slot { font-size: clamp(30px, 8vw, 44px); line-height: 1; min-height: 1.1em; }
.dt-num { font-size: clamp(14px, 3.5vw, 18px); font-weight: 900; color: var(--ink-soft); }
.dt-houses.ok .dt-house { border-color: var(--good); }
.dt-houses.shake { animation: shake .38s ease; }
.dt-tray { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; margin-bottom: 18px; }

/* ---------- teka-teki zebra ---------- */
.zb-grid { display: grid; gap: 6px; margin-bottom: 16px; align-items: center; }
.zb-hdr {
  font-size: 10.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .3px; color: var(--ink-soft); text-align: center;
}
.zb-who { font-size: 24px; text-align: center; }
.zb-cell {
  aspect-ratio: 1; border: 2px dashed var(--line); border-radius: var(--r-sm);
  background: rgba(255,253,249,.6); font-size: 24px; line-height: 1;
  cursor: pointer; display: grid; place-items: center; padding: 0;
}
.zb-cell.filled { border-style: solid; background: var(--surface); box-shadow: var(--shadow); }
.zb-cell.hinted { border-color: var(--star); }
.zb-grid.ok .zb-cell { border-color: var(--good); }
.zb-grid.shake { animation: shake .38s ease; }
.zb-trays { display: flex; flex-direction: column; gap: 8px; margin-bottom: 18px; }
.zb-tray { display: flex; gap: 8px; justify-content: center; }


/* ==========================================================================
   Paket G — Cari Kata Tersulit, Labirin Monster
   ========================================================================== */

/* ---------- cari kata tersulit ---------- */
.hs-bar {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 12px; flex-wrap: wrap; margin-bottom: 6px;
}
.hs-target { flex: 1 1 auto; min-width: 0; }
.hs-target { font-size: 14px; font-weight: 800; color: var(--ink-soft); }
.hs-target b { color: var(--ink); font-size: 17px; letter-spacing: 2px; }
.hs-time {
  font-size: 17px; font-weight: 800; color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}
.hs-time.low { color: var(--warn); }
.hs-note { font-size: 11.5px; color: var(--ink-soft); line-height: 1.5; margin-bottom: 12px; }
/* Matched to the ordinary Wordsearch board: real gaps between cells and a
   rounded tile each, so the grid reads as separate squares instead of a
   solid block of letters. The gap costs width, which is the trade Bena
   accepted — tidy beats big here. */
.hs-board-main {
  width: 100%; padding: 10px;
  border: 2px solid #4f8578; border-radius: var(--r-md);
  background: rgba(255,253,249,.94);
  box-shadow: 0 3px 0 rgba(63,125,116,.16);
}
.hs-grid {
  display: grid; gap: 3px; width: 100%; aspect-ratio: 1;
  background: transparent; border-radius: var(--r-sm);
  padding: 0; user-select: none; touch-action: none;
}
.hs-cell {
  display: grid; place-items: center;
  background: var(--surface); border: 1px solid rgba(36,32,28,.24); border-radius: 6px;
  box-sizing: border-box;
  font-weight: 800; color: var(--ink);
  box-shadow: 0 1px 0 rgba(120,100,80,.07);
  line-height: 1; cursor: pointer;
}
.hs-cell.sel   { background: var(--c2); color: #fff; }
.hs-cell.found-h { background: #f8dfc6; color: #8c5829; }
.hs-cell.found-v { background: #d9eee2; color: #3f725b; }
.hs-cell.found-d { background: #e8def4; color: #695184; }
.hs-cell.flash { animation: smflash .5s ease 3; }
.hs-grid.shake { animation: shake .3s ease; }

/* ---------- labirin monster (chip's-challenge style) ---------- */
.mo-hud {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  font-size: 12px; font-weight: 800; color: var(--ink-soft); margin-bottom: 10px;
}
.mo-hud span#mo-moves { color: var(--ink); }
.mo-keys { display: flex; gap: 5px; }
.mo-key { width: 20px; height: 20px; display: block; }
/* a key you have not found yet is drawn faint, so the HUD doubles as a checklist */
.mo-key { opacity: .2; filter: grayscale(1); }
.mo-key.have { opacity: 1; filter: none; }

/* minmax(0,1fr) is load-bearing: a bare 1fr is minmax(AUTO,1fr), so any content
   taller than its track stretches the row. That is why the emoji version came
   out 27px wide by 25px tall instead of square. */
.mo-grid {
  display: grid; gap: 1px; width: min(100%, 380px); aspect-ratio: 1;
  margin: 0 auto 14px; background: var(--line);
  border-radius: var(--r-sm); overflow: hidden; padding: 1px;
}
.mo-cell {
  background: var(--surface); position: relative;
  display: block; min-width: 0; min-height: 0; overflow: hidden;
}
/* Absolute, not height:100%. A percentage height needs a parent with a
   DEFINITE height, and a stretched grid item does not reliably provide one —
   the sprites collapsed to 22x2px on the 13x13 board while looking fine on the
   9x9. Pinning to the cell's edges removes the dependency entirely. */
.mo-svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.mo-cell.wall { background: var(--ink); }
.mo-cell.goal { background: #fbf3dd; }
.mo-cell.hero { background: #e2efe9; }
.mo-cell.hero.caught { background: var(--warn); }
.mo-cell.dark { background: #ece3d4; }
.mo-cell.flash { animation: smflash .5s ease 3; }
.mo-cell.shake { animation: shake .3s ease; }

/* ---------- tali melingkar (slitherlink) ----------
   The board is one grid of 2n+1 tracks: even tracks hold the dots, odd tracks
   are the gaps between them, so dots / edges / clue numbers all land in place
   without absolute positioning. */
/* width:100% is required, not cosmetic: the play stage centres its children,
   so without it this wrapper shrinks to its content and the board rendered
   159px wide on a 375px phone — the "kecil banget" Bena reported. */
.sl-wrap { display: flex; justify-content: center; width: 100%; margin-bottom: 18px; }
.sl-grid {
  display: grid; width: 100%; aspect-ratio: 1;
  background: var(--surface); border-radius: var(--r-md);
  padding: 12px; box-shadow: var(--shadow);
}
/* the wrapper carries the cap, not the grid, so the board fills the phone
   width instead of sitting as a small stamp in the middle of the screen */
.sl-wrap > .sl-grid { max-width: 460px; }
.sl-dot { border-radius: 50%; background: var(--ink-soft); opacity: .6; }
.sl-cell {
  display: grid; place-items: center;
  font-weight: 800; font-size: 17px; color: var(--ink);
}
/* generous tap targets: the visible line is thin but the hit area is the
   whole track, which matters a lot on a phone */
.sl-edge { position: relative; cursor: pointer; }
.sl-edge::after {
  content: ''; position: absolute; background: var(--line); border-radius: 3px;
}
.sl-h::after { left: 0; right: 0; top: 50%; height: 3px; transform: translateY(-50%); }
.sl-v::after { top: 0; bottom: 0; left: 50%; width: 3px; transform: translateX(-50%); }
.sl-edge.on::after { background: var(--c6); }
.sl-h.on::after { height: 6px; }
.sl-v.on::after { width: 6px; }
.sl-edge.hinted::after { background: var(--star); }
.sl-grid.ok .sl-edge.on::after { background: var(--good); }
.sl-grid.shake { animation: shake .38s ease; }


/* ---------- tantangan (challenge result) ---------- */


/* ---------- challenge intro ---------- */
.ci-face { font-size: 54px; line-height: 1; margin-bottom: 6px; }


/* ---------- cut & fit: drag to place, tap to rotate ---------- */
.tg-hint-line {
  text-align: center; font-size: 11.5px; font-weight: 700;
  color: var(--ink-soft); margin-bottom: 12px;
}
.tg-piece { touch-action: none; }        /* let pointermove drag instead of scroll */
/* the piece follows the finger, offset up-left so it is not under the thumb */
.tg-ghost {
  position: fixed; pointer-events: none; z-index: 60;
  transform: translate(-50%, -130%); opacity: .9;
  filter: drop-shadow(0 6px 10px rgba(120,100,80,.3));
}
.tg-cell.preview     { background: rgba(111,174,155,.35); border-style: solid; }
.tg-cell.preview-bad { background: rgba(221,154,106,.3); border-style: solid; }


/* ---------- tebak rebus ----------
   The struck-out letter is the whole point of the puzzle, so the line through
   it has to be unmistakable — a thin text-decoration reads as a rendering
   glitch at this size. */
.rb-clue {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: 8px; margin: 14px 0 26px;
}
.rb-pic { font-size: 44px; line-height: 1; }
.rb-op { font-size: 26px; font-weight: 800; color: var(--ink-soft); }
.rb-letter {
  position: relative;
  display: inline-grid; place-items: center;
  min-width: 1.5em; padding: 2px 6px;
  background: var(--surface); border-radius: var(--r-sm); box-shadow: var(--shadow);
  font-size: 26px; font-weight: 800; color: var(--ink); letter-spacing: 1px;
}
.rb-cut { color: var(--warn); }
.rb-cut::after {
  content: ''; position: absolute; left: 8%; right: 8%; top: 50%;
  height: 3px; background: var(--warn); border-radius: 2px;
  transform: rotate(-14deg);
}
.rb-q {
  font-size: 30px; font-weight: 800; color: var(--c2);
  min-width: 1.2em; text-align: center;
}


/* ---------- sirkuit lampu ----------
   Restored after being destroyed by a marker-based slice edit: this block sat
   between the monster and slitherlink markers, so replacing "everything from
   monster to slitherlink" silently took it with it and the game rendered as a
   blank screen. Never slice CSS by neighbouring section markers again. */
.li-hud { text-align: center; font-size: 12px; font-weight: 800; color: var(--ink-soft); margin-bottom: 14px; }
.li-hud span { color: var(--ink); }
.li-grid {
  display: grid; gap: 8px; width: min(100%, 300px); aspect-ratio: 1; margin: 0 auto;
  grid-auto-rows: minmax(0, 1fr);
}
.li-cell {
  border: none; border-radius: var(--r-md); padding: 0; min-width: 0; min-height: 0;
  background: #ded3c2; box-shadow: var(--shadow); cursor: pointer;
  transition: background .12s ease, transform .1s ease;
}
.li-cell.on { background: var(--star); box-shadow: 0 0 0 2px rgba(237,195,92,.35), var(--shadow); }
.li-cell:active { transform: scale(.93); }
.li-cell.flash { animation: smflash .5s ease 3; }
.li-grid.ok .li-cell { background: var(--good); }


/* a rule reminder that stays on the board — the how-to modal is seen once and
   Slitherlink is the one game whose goal is not guessable from looking at it */
.sl-tip {
  font-size: 11.5px; line-height: 1.5; color: var(--ink-soft);
  text-align: center; margin-bottom: 12px;
}

/* hazard tiles fill their cell edge to edge, so a pool reads as terrain
   rather than as an object sitting on the floor */
.mo-cell.hazard { background: transparent; }


/* ---------- Bridges (Hashiwokakero) ---------- */
.hs-wrap {
  display: flex; flex-direction: column; align-items: center; gap: 22px;
  width: 100%; height: 100%; padding: 4px 18px 0;
}
.hs-tip {
  font-size: 12px; font-weight: 700; color: var(--ink-soft);
  text-align: center; line-height: 1.4;
}
.hs-board { position: relative; width: 100%; max-width: min(100%, 390px); }
.hs-board::before {
  content: ''; position: absolute; inset: -14px; z-index: 0;
  background: var(--surface); border: 3px solid var(--ink-line);
  border-radius: var(--r-md); box-shadow: var(--shadow);
}
.hs-lines {
  position: absolute; inset: 0; width: 100%; height: 100%; z-index: 1;
  pointer-events: none; overflow: visible;
}
.hs-lines line {
  stroke: var(--ink-line); stroke-width: .07; stroke-linecap: round;
}
.hs-board.ok .hs-lines line { stroke: var(--good); }
.hs-node {
  position: absolute; border-radius: 50%; padding: 0;
  background: var(--surface); border: 2.5px solid var(--ink-line);
  color: var(--ink); font: inherit; font-weight: 800; line-height: 1;
  display: grid; place-items: center; cursor: pointer; z-index: 2;
}
.hs-node.full { background: var(--bg-soft); color: var(--ink-soft); }
.hs-node.over { background: var(--warn); color: #fff; }
.hs-node.sel  { background: var(--c1); color: #fff; transform: scale(1.12); }
.hs-node.bump { animation: hsbump .3s ease; }
@keyframes hsbump { 0%,100%{transform:scale(1)} 50%{transform:scale(1.18)} }
.hs-board.ok .hs-node { border-color: var(--good); }

/* ---------- Battleships (Bimaru) ---------- */
.bm-wrap { display: flex; flex-direction: column; align-items: center; gap: 10px;
  width: 100%; min-width: 0; height: 100%; }
.bm-fleet {
  font-size: 12.5px; font-weight: 800; color: var(--ink-soft);
  background: var(--bg-soft); border-radius: 999px; padding: 5px 14px;
}
.bm-grid {
  position: relative; min-width: 0;
  display: grid; gap: 3px; width: 100%; max-width: min(100%, 420px);
}
.bm-ship-art {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none; z-index: 1; mix-blend-mode: multiply;
}
.bm-corner { min-width: 0; aspect-ratio: 1; }
.bm-count {
  min-width: 0; aspect-ratio: 1; display: grid; place-items: center;
  font-size: 13px; font-weight: 800; color: var(--ink-soft);
}
.bm-count.met  { color: var(--good); }
.bm-count.bust { color: var(--warn); }
.bm-cell {
  min-width: 0; aspect-ratio: 1; padding: 0; border-radius: 6px;
  background: var(--surface); border: 2px solid var(--line);
  cursor: pointer; position: relative;
}
.bm-cell.ship  { background: var(--ink-line); border-color: var(--ink-line); }
.bm-cell.water { background: var(--bg-soft); border-color: var(--line); }
/* water reads as a dot, so an untouched square is never mistaken for it */
.bm-cell.water::after {
  content: ''; position: absolute; left: 50%; top: 50%;
  width: 22%; height: 22%; margin: -11% 0 0 -11%;
  border-radius: 50%; background: var(--ink-soft); opacity: .55;
}
.bm-cell.given { box-shadow: inset 0 0 0 2px var(--c4); }
.bm-grid.ok .bm-cell.ship { background: var(--good); border-color: var(--good); }

/* ---------- Killer Sudoku ---------- */
.ks-wrap { display: flex; flex-direction: column; align-items: center; gap: 12px;
  width: 100%; height: 100%; }
.ks-grid {
  display: grid; width: 100%; max-width: min(100%, 420px);
  background: var(--surface); border: 3px solid var(--ink-line); border-radius: 3px;
}
.ks-cell {
  position: relative; aspect-ratio: 1; padding: 0; border: none; background: transparent;
  cursor: pointer; display: grid; place-items: center;
  font: inherit; font-weight: 700; color: var(--c1);
  /* the pale sudoku lattice; heavier box lines and cage dashes sit on top */
  box-shadow: inset -1px -1px 0 var(--line);
}
.ks-grid.n9 .ks-cell { font-size: 15px; }
.ks-grid.n6 .ks-cell { font-size: 18px; }
.ks-cell.given { color: var(--ink); font-weight: 900; }
.ks-cell.sel { background: rgba(63,125,116,.16); }
.ks-cell.bad { color: var(--warn); }
.ks-cell.cagedone .ks-v { color: var(--good); }
.ks-grid.ok .ks-cell { color: var(--good); }

/* sudoku box rules — drawn as real borders so they read heavier than the cage dashes */
.ks-cell.bt { border-top: 2px solid var(--ink-line); }
.ks-cell.bl { border-left: 2px solid var(--ink-line); }
.ks-cell.bb { border-bottom: 2px solid var(--ink-line); }
.ks-cell.br { border-right: 2px solid var(--ink-line); }

/* Cage outlines are one SVG layer over the whole grid — see drawCages() in
   killer.js for why per-cell borders could not be made to join up. The layer
   sits above the cells but takes no pointer events, so tapping still works. */
.ks-grid { position: relative; }
.ks-cages {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none; z-index: 2; overflow: visible;
}
/* muted, not the loud accent — the cages annotate, they do not compete */
.ks-cages path { stroke: #9c8b78; }

.ks-sum {
  position: absolute; top: 2px; left: 4px; font-style: normal;
  font-size: 9px; font-weight: 900; color: var(--c3); line-height: 1;
  letter-spacing: -.02em;
}
.ks-grid.n6 .ks-sum { font-size: 12px; }
.ks-v { line-height: 1; padding-top: 5px; }

.ks-pad { display: grid; gap: 6px; width: 100%; max-width: min(100%, 360px); }
.ks-key {
  padding: 12px 0; border: none; border-radius: var(--r-sm);
  background: var(--surface); box-shadow: 0 3px 0 var(--line);
  font: inherit; font-size: 18px; font-weight: 800; color: var(--ink); cursor: pointer;
}
.ks-key:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--line); }
.ks-key.del { background: var(--bg-soft); }

/* ---------- Sudoku variants (Thermo / Arrow / Sandwich) ----------
   One layout for all three. The wrapper takes the full stage width on
   purpose: .play-stage centres its children, so a wrapper without a width
   collapses to its content and every percentage inside it measures against
   nothing — the sizing bug that shipped three times before this. */
.sv-wrap {
  display: flex; flex-direction: column; align-items: center; gap: 14px;
  width: 100%; height: auto; flex: none; padding: 4px 14px 8px;
}
.sv-wrap > * { flex-shrink: 0; }
.sv-tip {
  font-size: 12.5px; font-weight: 700; color: var(--ink-soft);
  text-align: center; line-height: 1.4; max-width: 46ch;
}
/* the plain panel that keeps the board off the stage's paper texture */
.sv-panel {
  position: relative; width: 100%; max-width: min(100%, 400px);
  background: var(--surface); border: 3px solid var(--ink-line);
  border-radius: var(--r-md); box-shadow: var(--shadow); padding: 6px;
}
.sv-grid { display: grid; width: 100%; position: relative; z-index: 1; }
.sv-cell {
  position: relative; aspect-ratio: 1; padding: 0; border: none;
  background: transparent; cursor: pointer; display: grid; place-items: center;
  font: inherit; font-weight: 700; color: var(--c1);
  box-shadow: inset -1px -1px 0 var(--line);
}
.sv-grid.n9 .sv-cell { font-size: 16px; }
.sv-grid.n6 .sv-cell { font-size: 19px; }
.sv-cell.given { color: var(--ink); font-weight: 900; }
.sv-cell.sel { background: rgba(63,125,116,.16); }
.sv-cell.bad { color: var(--warn); }
.sv-grid.ok .sv-cell { color: var(--good); }
.sv-cell.bt { border-top: 2px solid var(--ink-line); }
.sv-cell.bl { border-left: 2px solid var(--ink-line); }
.sv-cell.bb { border-bottom: 2px solid var(--ink-line); }
.sv-cell.br { border-right: 2px solid var(--ink-line); }
.sv-v { line-height: 1; position: relative; z-index: 2; }

/* Clue art normally sits UNDER the digits — thermo tubes and arrow lines are
   large translucent shapes and must not wash the numbers out. Kropki is the
   exception: its dots straddle the wall between two squares, and the cells'
   own heavy box borders were painting straight over them, so that variant
   lifts the art above the grid instead. */
.sv-panel.art-top .sv-grid { z-index: 0; }
.sv-panel.art-top .sv-art  { z-index: 1; }
.sv-art {
  position: absolute; left: 6px; top: 6px;
  width: calc(100% - 12px); height: calc(100% - 12px);
  pointer-events: none; z-index: 0; overflow: visible;
}

.sv-pad { display: grid; gap: 6px; width: 100%; max-width: min(100%, 360px); }
.sv-key {
  padding: 12px 0; border: none; border-radius: var(--r-sm);
  background: var(--surface); box-shadow: 0 3px 0 var(--line);
  font: inherit; font-size: 18px; font-weight: 800; color: var(--ink); cursor: pointer;
}
.sv-key:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--line); }
.sv-key.del { background: var(--bg-soft); }

/* thermo: a bulb and a fat track the digits must climb */
.sv-thermo { stroke: rgba(47,42,38,.22); stroke-width: .34; fill: none;
  stroke-linecap: round; stroke-linejoin: round; }
.sv-bulb { fill: rgba(47,42,38,.22); }

/* arrow: circle holds the total, the tail carries the digits that make it */
.sv-arrowline { stroke: rgba(74,111,165,.5); stroke-width: .07; fill: none;
  stroke-linecap: round; stroke-linejoin: round; }
.sv-arrowhead { fill: rgba(74,111,165,.5); }
.sv-circle { fill: none; stroke: rgba(74,111,165,.55); stroke-width: .07; }

/* sandwich: clues live outside the grid, so the panel gets room for them */
.sv-panel.has-edge { padding: 6px 6px 6px 30px; }
.sv-panel.has-edge .sv-art { left: 30px; width: calc(100% - 36px); }
.sv-edge { position: absolute; font-weight: 900; color: var(--c3); font-size: 12px; }
.sv-edge.left { left: 6px; width: 22px; text-align: center; }
.sv-edge.top  { top: 6px; height: 22px; line-height: 22px; text-align: center; }
.sv-panel.has-edge { padding-top: 30px; }
.sv-panel.has-edge .sv-art { top: 30px; height: calc(100% - 36px); }

/* ---------- Knights & Knaves ---------- */
.kn-wrap {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  width: 100%; height: 100%; padding: 4px 14px 0;
}
.kn-tip {
  font-size: 12.5px; font-weight: 700; color: var(--ink-soft);
  text-align: center; line-height: 1.4; max-width: 46ch;
}
/* a plain card, so the statements are not read against the stage texture */
.kn-panel {
  width: 100%; max-width: min(100%, 420px);
  background: var(--surface); border: 3px solid var(--ink-line);
  border-radius: var(--r-md); box-shadow: var(--shadow);
  padding: 6px; display: flex; flex-direction: column; gap: 6px;
}
.kn-row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 11px; border-radius: var(--r-sm); background: var(--bg-soft);
}
.kn-who { flex: 1; min-width: 0; }
.kn-name { display: block; font-weight: 900; font-size: 14.5px; color: var(--ink); }
.kn-said { display: block; font-size: 13px; color: var(--ink-soft); line-height: 1.45; }
.kn-pick { display: flex; gap: 6px; flex: none; }
.kn-btn {
  border: 2px solid var(--line); border-radius: 999px;
  padding: 7px 13px; font: inherit; font-size: 12.5px; font-weight: 800;
  background: var(--surface); color: var(--ink-soft); cursor: pointer;
}
.kn-btn.kn-t.on { background: var(--good); border-color: var(--good); color: #fff; }
.kn-btn.kn-f.on { background: var(--c3);  border-color: var(--c3);  color: #fff; }
.kn-panel.ok .kn-row { background: rgba(79,143,120,.16); }

/* kropki dots sit on the wall between two squares */
.kr-dot { stroke: var(--ink-line); stroke-width: .035; }
.kr-w { fill: var(--surface); }
.kr-b { fill: var(--ink-line); }

/* ---------- Tents & Trees ---------- */
.tn-wrap {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  width: 100%; height: 100%; padding: 4px 14px 0;
}
.tn-tip {
  font-size: 12.5px; font-weight: 700; color: var(--ink-soft);
  text-align: center; line-height: 1.4; max-width: 46ch;
}
.tn-panel {
  width: 100%; max-width: min(100%, 400px);
  background: var(--surface); border: 3px solid var(--ink-line);
  border-radius: var(--r-md); box-shadow: var(--shadow); padding: 6px;
}
.tn-grid { display: grid; gap: 2px; width: 100%; }
.tn-cell {
  aspect-ratio: 1; display: grid; place-items: center;
  font-size: 15px; line-height: 1; padding: 0; border: none;
}
.tn-corner { background: transparent; }
.tn-count {
  aspect-ratio: 1; display: grid; place-items: center;
  font-size: 13px; font-weight: 800; color: var(--ink-soft);
}
.tn-count.met  { color: var(--good); }
.tn-count.bust { color: var(--warn); }
.tn-tree { background: var(--bg-soft); border-radius: 5px; }
.tn-plot {
  background: var(--surface); border: 2px solid var(--line);
  border-radius: 5px; cursor: pointer;
}
/* grass is a dot, so an untouched square never reads as "ruled out" */
.tn-plot.grass { background: var(--bg-soft); position: relative; }
.tn-plot.grass::after {
  content: ''; position: absolute; left: 50%; top: 50%;
  width: 20%; height: 20%; margin: -10% 0 0 -10%;
  border-radius: 50%; background: var(--ink-soft); opacity: .5;
}
.tn-grid.ok .tn-plot { border-color: var(--good); }

/* Skyscrapers: clues ring the grid on all four sides, so the panel is inset
   to make room and the numbers are positioned against it. */
.sv-panel.has-ring { padding: 28px; }
.sv-panel.has-ring .sv-art { left: 28px; top: 28px;
  width: calc(100% - 56px); height: calc(100% - 56px); }
.sv-ring {
  position: absolute; font-weight: 900; font-size: 13px; color: var(--c2);
  width: 22px; height: 20px; display: grid; place-items: center;
}

/* ---------- Dominosa ---------- */
.dm-wrap {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  width: 100%; height: 100%; padding: 4px 14px 0;
}
.dm-tip {
  font-size: 12.5px; font-weight: 700; color: var(--ink-soft);
  text-align: center; line-height: 1.4; max-width: 46ch;
}
.dm-panel {
  width: 100%; max-width: min(100%, 400px);
  background: var(--surface); border: 3px solid var(--ink-line);
  border-radius: var(--r-md); box-shadow: var(--shadow); padding: 7px;
}
.dm-grid { display: grid; gap: 3px; width: 100%; }
.dm-cell {
  aspect-ratio: 1; padding: 0; border: 2px solid var(--line);
  border-radius: 7px; background: var(--surface); cursor: pointer;
  font: inherit; font-weight: 800; font-size: 16px; color: var(--ink);
}
.dm-cell.sel { background: rgba(63,125,116,.18); border-color: var(--c1); }
/* a joined pair loses the wall between its two halves, so it reads as one tile */
.dm-cell.joined { background: var(--bg-soft); border-color: var(--ink-line); }
.dm-cell.jr { border-right-color: transparent; border-top-right-radius: 0; border-bottom-right-radius: 0; }
.dm-cell.jl { border-left-color: transparent;  border-top-left-radius: 0;  border-bottom-left-radius: 0; }
.dm-cell.jd { border-bottom-color: transparent; border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.dm-cell.ju { border-top-color: transparent;    border-top-left-radius: 0;    border-top-right-radius: 0; }
.dm-grid.ok .dm-cell.joined { background: rgba(79,143,120,.2); border-color: var(--good); }

/* ---- Suguru ------------------------------------------------------------
   Cage walls are drawn as thick borders on the cells that sit just inside a
   boundary, so a cage reads as one enclosed pen. The panel is a plain
   surface, so the board never blends into the page's checked background. */
.sg-wrap {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  width: 100%; height: 100%; padding: 4px 14px 0;
}
.sg-tip {
  font-size: 12.5px; font-weight: 700; color: var(--ink-soft);
  text-align: center; line-height: 1.4; max-width: 46ch;
}
.sg-panel {
  width: 100%; max-width: min(100%, 380px);
  background: var(--surface); border: 3px solid var(--ink-line);
  border-radius: var(--r-md); box-shadow: var(--shadow); padding: 8px;
}
.sg-grid { display: grid; gap: 0; width: 100%; }
.sg-cell {
  aspect-ratio: 1; padding: 0; cursor: pointer; font: inherit;
  font-weight: 800; font-size: 16px; color: var(--c1);
  background: var(--surface); border: 1px solid var(--line);
}
/* the four cage walls */
.sg-cell.wt { border-top-width: 3px;    border-top-color: var(--ink-line); }
.sg-cell.wl { border-left-width: 3px;   border-left-color: var(--ink-line); }
.sg-cell.wb { border-bottom-width: 3px; border-bottom-color: var(--ink-line); }
.sg-cell.wr { border-right-width: 3px;  border-right-color: var(--ink-line); }
.sg-cell.given { color: var(--ink); background: var(--bg-soft); cursor: default; }
.sg-cell.sel { background: rgba(63,125,116,.18); }
.sg-cell.bad { color: #c4796a; background: #f7dcd6; }
.sg-grid.ok .sg-cell { background: rgba(79,143,120,.18); }
.sg-pad { display: grid; gap: 6px; width: 100%; max-width: min(100%, 380px); }
.sg-key {
  padding: 11px 0; border: 2px solid var(--ink-line); border-radius: var(--r-sm);
  background: var(--surface); font: inherit; font-weight: 800; font-size: 17px;
  color: var(--ink); cursor: pointer; box-shadow: 0 2px 0 var(--ink-line);
}
.sg-key:active { transform: translateY(2px); box-shadow: none; }
.sg-key.del { color: var(--ink-soft); }

/* ---- Binairo ------------------------------------------------------------
   Two tokens rather than digits: the puzzle has no reading or arithmetic in
   it, and the art should not add any. Givens are the filled discs with a ring;
   the player's own marks are the same discs without one, so a glance separates
   what was handed to you from what you worked out. */
.bn-wrap {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  width: 100%; height: 100%; padding: 4px 14px 0;
}
.bn-tip {
  font-size: 12.5px; font-weight: 700; color: var(--ink-soft);
  text-align: center; line-height: 1.4; max-width: 46ch;
}
.bn-panel {
  width: 100%; max-width: min(100%, 400px);
  background: var(--surface); border: 3px solid var(--ink-line);
  border-radius: var(--r-md); box-shadow: var(--shadow); padding: 7px;
}
.bn-grid { display: grid; gap: 2px; width: 100%; }
.bn-cell {
  aspect-ratio: 1; padding: 0; cursor: pointer; font: inherit;
  border: 1px solid var(--line); border-radius: 5px;
  background: var(--surface);
  display: flex; align-items: center; justify-content: center;
}
.bn-cell > i {
  display: block; width: 68%; height: 68%; border-radius: 50%;
  background: transparent; transition: background .12s;
}
.bn-cell.a > i { background: var(--star); }
.bn-cell.b > i { background: var(--c2); }
.bn-cell.sel { outline: 3px solid var(--c1); outline-offset: -2px; }
/* a given is locked in — the heavier ring says "this one was not your doing" */
.bn-cell.given { background: var(--bg-soft); cursor: default; }
.bn-cell.given > i { box-shadow: 0 0 0 2px var(--ink-line) inset; }
.bn-cell.bad > i { background: #c4796a; }
.bn-cell.bad { background: #f7dcd6; }
.bn-warning {
  width: 100%; max-width: min(100%, 400px); padding: 8px 12px;
  border: 2px solid #c94c6d; border-radius: var(--r-sm);
  background: #fff0f4; color: #7f2943;
  font-size: 12px; font-weight: 900; line-height: 1.35; text-align: center;
}
.bn-warning[hidden] { display: none; }
.bn-grid.ok .bn-cell { border-color: var(--good); }

/* ---- Monthly Leaderboard ------------------------------------------------ */
.lead-face { position: relative; }
/* Green up, red down — compared against the standing the player last saw. */
.lead-arrow { font-size: 11px; margin-right: 4px; vertical-align: 1px; }
.lead-arrow.up { color: var(--good); }
.lead-arrow.down { color: #c4796a; }
.lg-title { font-size: 15px; font-weight: 900; }

/* Number Pattern's clue line: shown only after the player asks for it. */
.pt-clue {
  max-width: 46ch; margin: 0 auto 14px; padding: 10px 14px;
  border: 2px dashed var(--ink-line); border-radius: var(--r-sm);
  background: rgba(217,164,65,.14);
  font-size: 13.5px; font-weight: 700; line-height: 1.45; text-align: center;
}

/* Battleships fleet strip: every ship drawn at its true length, so "how many"
   and "how long" are both read off the picture instead of from a × notation
   that people reliably misread as a shape. */
.bm-fleet {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px;
  margin-bottom: 10px; padding: 8px 10px;
  background: var(--surface); border: 2px solid var(--ink-line);
  border-radius: var(--r-sm);
}
.bm-fleet-lbl { font-size: 15px; margin-right: 2px; }
.bm-ship { display: inline-flex; gap: 2px; }
.bm-ship i {
  width: 11px; height: 11px; border-radius: 2px;
  background: var(--c2); display: block;
}

/* Futoshiki sits on a plain panel so the > and < signs between cells are not
   read against the page's checked background. */
.fu-panel {
  width: 100%; max-width: min(100%, 400px); margin: 0 auto;
  background: var(--surface); border: 3px solid var(--ink-line);
  border-radius: var(--r-md); box-shadow: var(--shadow); padding: 10px;
}

.acct-email-note {
  margin: -4px 2px 10px; color: var(--ink-soft); font-size: 11.5px;
  line-height: 1.45; text-align: left;
}
.acct-email-hint {
  margin: -3px 2px 10px; padding: 8px 10px; border-radius: var(--r-sm);
  background: rgba(217,164,65,.16); color: var(--ink); font-size: 12px;
  line-height: 1.4; text-align: left;
}
.acct-email-hint button {
  padding: 0; border: 0; background: none; color: var(--c1);
  font: inherit; font-weight: 900; text-decoration: underline; cursor: pointer;
}
.acct-support {
  min-height: 44px; flex: 1; display: flex; align-items: center; justify-content: center;
  margin: 0; padding: 9px 11px; background: var(--surface); border: 2px solid var(--ink-line);
  border-radius: 12px; color: var(--c1); font-size: 13px; font-weight: 900;
  text-align: center; text-underline-offset: 3px;
}

/* "Lupa Password?" — shown only under the sign-in form, hidden on sign-up
   where there is no existing password to forget. Bold and full-size so it
   reads as an action, not fine print — Bena's ask after two people missed it
   entirely on the muted first version. Toggled in account.js. */
.acct-forgot {
  min-height: 44px; flex: 1; display: flex; align-items: center; justify-content: center;
  width: auto; margin: 0; padding: 9px 11px; background: var(--bg-soft);
  border: 2px solid var(--ink-line); border-radius: 12px; font: inherit; font-size: 13px;
  font-weight: 900; color: var(--ink); text-decoration: underline;
  text-align: center; cursor: pointer;
}

/* Password fields with a show/hide eye button. The wrapper carries the
   margin the plain .acct-input used to have on its own, since the input no
   longer manages its own spacing once it shares a row with the button. */
.pw-field { position: relative; margin-bottom: 10px; }
.pw-field .acct-input { margin-bottom: 0; padding-right: 46px; }
.pw-eye {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  width: 34px; height: 34px; padding: 0;
  background: none; border: none; font-size: 18px; line-height: 1;
  color: var(--ink-soft); cursor: pointer; opacity: .65;
}
.pw-eye.on { opacity: 1; }

/* Context-aware music picker, reached from the 🎵 app-bar icon. */
.mus-row { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; flex: none; }
.mus-btn {
  min-height: 44px; flex: 1 1 calc(50% - 8px); padding: 10px 8px; font: inherit; font-size: 12.5px; font-weight: 800;
  border: 2px solid var(--ink-line); border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink); cursor: pointer;
}
.mus-btn.on { background: var(--c1); color: #fff; }
.mus-btn:disabled { cursor: not-allowed; opacity: .52; background: var(--bg-soft); color: var(--ink-soft); }
.mus-btn span, .mus-btn small { display: block; }
.mus-btn small { margin-top: 3px; font-size: 10px; font-weight: 700; line-height: 1.2; }
.audio-file-picker[hidden] { display: none; }
.audio-track-section { margin: 0 0 16px; text-align: left; }
.audio-track-section h4, .audio-repeat-group legend {
  margin: 0 0 7px; color: var(--ink); font-size: 13px; font-weight: 900;
}
.audio-repeat-group { min-width: 0; margin: 0 0 14px; padding: 0; border: 0; text-align: left; }
.audio-repeat-row { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.audio-playback-status {
  min-height: 36px; margin: 0; padding: 9px 10px; border-radius: var(--r-sm);
  background: var(--bg-soft); color: var(--ink-soft); font-size: 11.5px; line-height: 1.4;
  text-align: left;
}

.audio-mute-row {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; padding: 14px;
  border: 2px solid var(--ink-line); border-radius: var(--r-md);
  background: var(--surface); color: var(--ink);
  font: inherit; font-size: 15px; font-weight: 800; text-align: center;
  cursor: pointer; margin: 4px 0 18px;
}
.audio-mute-row.is-off { color: var(--ink-soft); }
.audio-device-volume-note {
  margin: 0 0 18px; color: var(--ink-soft); font-size: 13px;
  line-height: 1.5; text-align: left;
}
.audio-volume-head {
  display: flex; justify-content: space-between; align-items: center;
  margin: 0 2px 4px; font-size: 13px; font-weight: 800; color: var(--ink-soft);
}
.audio-volume-head output { color: var(--ink); font-variant-numeric: tabular-nums; }
.audio-volume {
  display: block; width: 100%; margin: 0 0 20px;
  accent-color: var(--c1); cursor: pointer;
}
/* Daily Challenge menu. Gameplay itself reuses the full-size real engines. */
.challenge-card{width:min(620px,calc(100vw - 20px));max-height:92dvh;overflow:auto;padding:24px 20px!important;box-sizing:border-box}
.challenge-card .modal-title{padding-right:35px}.challenge-body{display:grid;gap:14px}.challenge-body p{margin:0;line-height:1.55}
.challenge-slot{display:flex;align-items:center;flex-wrap:wrap;gap:10px;padding:14px;background:#f7edde;border-radius:18px}
.challenge-slot strong{flex:1 1 150px}.challenge-slot span{font-size:14px}.challenge-slot button{min-height:44px}
.challenge-total{font-size:24px;font-weight:900;color:#28736b}.challenge-small{font-size:14px;color:#71685c}
.challenge-final-total{margin:0;padding:16px;border:2px solid #83bcb4;border-radius:16px;background:#e5f3ef;font-size:clamp(32px,9vw,46px);text-align:center;font-variant-numeric:tabular-nums}
.challenge-notice{min-height:24px;line-height:1.5;margin:16px 0 0;color:#715600}.challenge-intro{font-size:16px}
.draft-resume-notice{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;padding:8px 12px;border:2px solid rgba(63,125,116,.32);border-radius:14px;background:#eef8f4;color:var(--ink);font-size:13px;font-weight:800}
.draft-resume-notice button{border:0;background:none;color:var(--c1);font:inherit;text-decoration:underline;white-space:nowrap;cursor:pointer}
.challenge-link{background:none;border:0;text-decoration:underline;color:#337d74;cursor:pointer;font:inherit;padding:10px;min-height:44px}
.challenge-home{background:#fff0ab!important;color:var(--ink)!important;cursor:pointer;gap:12px}.challenge-home .dc-game{font-size:clamp(18px,4vw,26px)}
.challenge-progress{padding:16px}.challenge-progress p{margin:8px 0}.challenge-progress small{display:block;color:#896425}
.challenge-play-status{display:grid;grid-template-columns:1fr auto;gap:4px 12px;align-items:center;flex:1 0 100%;box-sizing:border-box;padding:9px 12px;border:2px solid var(--ink-line);border-radius:14px;background:#fff0ab;color:var(--ink);font-size:13px;font-weight:800;font-variant-numeric:tabular-nums}
.challenge-play-status b{text-align:right}.challenge-play-status small{grid-column:1/-1;min-height:0;color:#715600;font-weight:700;line-height:1.35}
.ws-grid.is-busy{pointer-events:none;opacity:.72}
@media(max-width:400px){.challenge-card{padding:20px 12px!important}.challenge-slot{padding:12px}.challenge-home{flex-wrap:wrap}.challenge-play-status{font-size:12px;padding:8px 10px}}
