/* ============================================================
   MONKU — stylesheet
   Ported from Review Buddies with a CSS-variable refactor and
   a warm "temple" palette: rice paper, ink, saffron, jade.
   Mobile/tablet-first, fluid clamp() sizing, no media queries.
   ============================================================ */

:root {
  /* palette */
  --paper: #FDF6EC;          /* rice-paper page background */
  --card: #FFFFFF;           /* card surfaces */
  --ink: #33291F;            /* main text (dark ink brown) */
  --muted: #8D8578;          /* secondary text */
  --heading: #7A4A12;        /* headings (roasted saffron) */
  --border: #E6DCC9;         /* card borders */

  --primary: #E8912D;        /* saffron — main action color */
  --primary-deep: #B96A15;   /* pressed shadow */
  --primary-soft: #FCEBD4;   /* saffron tint background */
  --primary-border: #F3CD9A; /* saffron tint border */

  --jade: #1D9E75;           /* correct / healthy HP */
  --jade-deep: #0F6E56;
  --jade-soft: #E1F5EE;
  --jade-border: #9FE1CB;

  --danger: #C43D3D;         /* wrong / final boss */
  --danger-deep: #A32D2D;
  --danger-soft: #FBEAEA;
  --danger-border: #F0BFBF;

  --gold: #F2C14E;           /* XP, stars, rewards */
  --gold-deep: #B98812;
  --gold-soft: #FBF0D5;

  --warn: #EF9F27;           /* mid HP */

  --sky-top: #F3E9FF;        /* arena sky */
  --sky-ground: #E4EFD6;     /* arena ground */

  --overlay: rgba(58, 42, 20, 0.55);       /* countdown overlay */
  --overlay-paper: rgba(253, 246, 236, 0.94); /* result overlay */
}

* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  height: 100%;
  font-family: "Segoe UI", Roboto, Arial, sans-serif;
  background: var(--paper);
  color: var(--ink);
  user-select: none;
  -webkit-user-select: none;
  overflow: hidden;
}

.screen {
  display: none;
  height: 100%;
  flex-direction: column;
  align-items: center;
  padding: 4vh 5vw;
  overflow-y: auto;
}
.screen.active { display: flex; }

/* ---------- SHARED TYPE ---------- */
.title {
  font-size: clamp(28px, 6vw, 44px);
  font-weight: 800;
  color: var(--heading);
  text-align: center;
}
.subtitle {
  font-size: clamp(16px, 3vw, 22px);
  color: var(--muted);
  margin: 8px 0 4vh;
  text-align: center;
}

/* ---------- SHARED BUTTONS ---------- */
.big-btn {
  margin-top: 4vh;
  font-size: clamp(20px, 4vw, 28px);
  font-weight: 800;
  color: #fff;
  background: var(--primary);
  border: none;
  border-radius: 999px;
  padding: 16px 54px;
  cursor: pointer;
  box-shadow: 0 6px 0 var(--primary-deep);
  transition: transform 0.1s, box-shadow 0.1s;
}
.big-btn:active { transform: translateY(4px); box-shadow: 0 2px 0 var(--primary-deep); }
.big-btn:disabled { opacity: 0.4; }

.small-btn {
  font-size: clamp(15px, 2.6vw, 19px);
  font-weight: 700;
  color: var(--primary-deep);
  background: var(--card);
  border: 3px solid var(--primary-border);
  border-radius: 999px;
  padding: 10px 26px;
  cursor: pointer;
}
.small-btn:active { transform: scale(0.95); }
.small-btn.primary { background: var(--primary); border-color: var(--primary); color: #fff; }

.tiny-btn {
  font-size: clamp(12px, 2.2vw, 15px);
  font-weight: 700;
  color: var(--muted);
  background: var(--card);
  border: 2px solid var(--border);
  border-radius: 999px;
  padding: 7px 14px;
  cursor: pointer;
  white-space: nowrap;
}
.tiny-btn:active { transform: scale(0.95); border-color: var(--primary-border); color: var(--primary-deep); }

.quiz-controls { display: flex; gap: 12px; margin-top: 2.5vh; flex-wrap: wrap; justify-content: center; }

/* ---------- TOGGLES ---------- */
.toggle-row {
  display: flex;
  gap: 10px;
  width: min(92vw, 520px);
  margin-bottom: 14px;
}
.toggle-btn {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  background: var(--card);
  border: 3px solid var(--border);
  border-radius: 16px;
  padding: 10px 8px;
  cursor: pointer;
  font-size: clamp(14px, 2.6vw, 18px);
  font-weight: 800;
  color: var(--muted);
}
.toggle-btn span { font-size: clamp(11px, 2vw, 13px); font-weight: 600; }
.toggle-btn.selected {
  border-color: var(--primary);
  background: var(--primary-soft);
  color: var(--heading);
}

/* ---------- TITLE SCREEN ---------- */
#title-screen { justify-content: center; }
.logo-mark {
  width: clamp(140px, 26vh, 220px);
  margin-bottom: 2vh;
  animation: bob 2.6s ease-in-out infinite;
}
.tagline {
  font-size: clamp(15px, 2.8vw, 20px);
  color: var(--muted);
  font-weight: 600;
  margin-top: 4px;
  text-align: center;
}

/* ---------- DOJO HOME ---------- */
#home-screen { padding-top: 2.5vh; }
.dojo-header {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  width: min(92vw, 560px);
  background: var(--card);
  border: 3px solid var(--border);
  border-radius: 20px;
  padding: 12px 16px;
}
/* On a narrow phone the streak and coin chips squeezed the name
   into a one-word-per-line column. Drop them onto their own row
   instead of letting them steal the text's width. */
.dojo-badges {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-shrink: 0;
}
@media (max-width: 460px) {
  .dojo-badges { flex-basis: 100%; justify-content: center; }
}
.dojo-avatar { width: clamp(74px, 14vh, 110px); flex-shrink: 0; }
.dojo-avatar svg { width: 100%; height: auto; display: block; }
.dojo-id { flex: 1 1 150px; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.dojo-name {
  font-size: clamp(17px, 3.2vw, 22px);
  font-weight: 800;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.dojo-rank {
  font-size: clamp(12px, 2.3vw, 15px);
  font-weight: 800;
  color: var(--heading);
}
.dojo-level {
  font-size: clamp(12px, 2.3vw, 15px);
  font-weight: 700;
  color: var(--muted);
}
.xp-bar {
  width: 100%;
  height: 14px;
  background: var(--paper);
  border: 2px solid var(--border);
  border-radius: 999px;
  overflow: hidden;
}
.xp-fill {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--gold), var(--primary));
  border-radius: 999px;
  transition: width 0.8s ease;
}
.xp-line {
  font-size: clamp(10px, 1.9vw, 13px);
  font-weight: 700;
  color: var(--muted);
}
.streak-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: clamp(12px, 2.3vw, 15px);
  font-weight: 800;
  color: var(--gold-deep);
  background: var(--gold-soft);
  border: 2px solid var(--gold);
  border-radius: 999px;
  padding: 4px 12px;
  flex-shrink: 0;
}
.dojo-week { width: min(92vw, 560px); margin-top: 10px; }
.dojo-menu {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: min(92vw, 560px);
  margin-top: 12px;
}
.menu-btn {
  display: flex;
  align-items: center;
  gap: 14px;
  background: var(--card);
  border: 3px solid var(--border);
  border-radius: 18px;
  padding: 14px 18px;
  cursor: pointer;
  text-align: left;
  transition: transform 0.12s, border-color 0.12s;
}
.menu-btn:active { transform: scale(0.97); border-color: var(--primary); }
.menu-btn .mb-icon { font-size: clamp(26px, 5vw, 36px); flex-shrink: 0; }
.menu-btn .mb-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.menu-btn .mb-title { font-size: clamp(16px, 3vw, 21px); font-weight: 800; color: var(--ink); }
.menu-btn .mb-sub { font-size: clamp(12px, 2.2vw, 15px); color: var(--muted); font-weight: 600; }
.menu-btn .mb-state { font-size: clamp(12px, 2.2vw, 15px); font-weight: 800; flex-shrink: 0; }
.menu-btn.quest { border-color: var(--primary); background: var(--primary-soft); }
.menu-btn.quest .mb-state { color: var(--primary-deep); }
.menu-btn.done { border-color: var(--jade-border); background: var(--jade-soft); }
.menu-btn.done .mb-state { color: var(--jade-deep); }
.home-foot {
  display: flex;
  gap: 10px;
  margin-top: 2vh;
  flex-wrap: wrap;
  justify-content: center;
}

/* ---------- LEVEL MAP (Mountain Path) ---------- */
.temple-list {
  display: flex;
  flex-direction: column-reverse; /* level 1 at the bottom — you climb up */
  gap: 8px;
  width: min(92vw, 560px);
  max-height: 62vh;
  overflow-y: auto;
  padding: 4px;
}
.temple-row {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--card);
  border: 3px solid var(--border);
  border-radius: 16px;
  padding: 10px 14px;
  text-align: left;
}
.temple-row .t-emoji { font-size: clamp(22px, 5vw, 32px); flex-shrink: 0; }
.temple-row .t-info { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.temple-row .t-name { font-size: clamp(13px, 2.5vw, 16px); font-weight: 800; color: var(--ink); }
.temple-row .t-topic { font-size: clamp(11px, 2vw, 13px); color: var(--muted); font-weight: 600; }
.temple-row .t-state { font-size: clamp(11px, 2.1vw, 14px); font-weight: 800; flex-shrink: 0; }
.temple-row.t-done { border-color: var(--jade-border); background: var(--jade-soft); }
.temple-row.t-done .t-state { color: var(--jade-deep); }
.temple-row.t-current { border-color: var(--primary); background: var(--primary-soft); border-width: 4px; }
.temple-row.t-current .t-state { color: var(--primary-deep); }
.temple-row.t-locked { opacity: 0.55; }
.mastery-pips { display: inline-flex; gap: 4px; margin-left: 6px; }
.pip {
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--paper);
  border: 2px solid var(--border);
  display: inline-block;
}
.pip.lit { background: var(--gold); border-color: var(--gold-deep); }

/* ---------- STAGE (placement / talking sensei) ---------- */
.quiz-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: min(92vw, 640px);
  margin-bottom: 1vh;
  gap: 8px;
}
.quiz-top .progress { margin-bottom: 0; }
.progress {
  font-size: clamp(14px, 2.5vw, 18px);
  color: var(--muted);
  font-weight: 700;
  margin-bottom: 1vh;
}
.stage {
  border-radius: 28px;
  padding: 14px 20px 10px;
  text-align: center;
  width: min(92vw, 460px);
  background: var(--primary-soft);
}
.char-holder { width: clamp(110px, 22vh, 160px); margin: 0 auto; transition: transform 0.3s; }
.char-holder.celebrate { animation: jump 0.5s ease 2; }
@keyframes jump {
  0%, 100% { transform: translateY(0); }
  40% { transform: translateY(-22px) rotate(-4deg); }
}
.char-name { font-weight: 800; font-size: clamp(15px, 2.6vw, 19px); color: var(--ink); }
.speech-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: rgba(255, 255, 255, 0.7);
  border-radius: 999px;
  padding: 6px 16px;
  font-size: clamp(13px, 2.3vw, 16px);
  color: var(--muted);
  margin-top: 6px;
  min-height: 32px;
}
.speech-pill .dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--primary);
  animation: pulse 0.9s infinite;
}
.speech-pill .dot:nth-child(2) { animation-delay: 0.15s; }
.speech-pill .dot:nth-child(3) { animation-delay: 0.3s; }
@keyframes pulse { 0%, 100% { opacity: 0.25; } 50% { opacity: 1; } }

/* ---------- QUESTIONS & CHOICES ---------- */
.question-text {
  font-size: clamp(20px, 3.6vw, 28px);
  font-weight: 800;
  color: var(--ink);
  margin: 2vh 0;
  text-align: center;
  max-width: 640px;
  line-height: 1.35;
}
.choices {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: min(92vw, 520px);
}
.choice-btn {
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: clamp(17px, 3vw, 23px);
  font-weight: 700;
  color: var(--ink);
  background: var(--card);
  border: 3px solid var(--border);
  border-radius: 18px;
  padding: 14px 18px;
  cursor: pointer;
  text-align: left;
  transition: transform 0.12s, border-color 0.12s, background 0.2s;
}
.choice-btn:active { transform: scale(0.97); }
.choice-btn .letter {
  flex-shrink: 0;
  width: 38px; height: 38px;
  border-radius: 50%;
  background: var(--primary-soft);
  color: var(--primary-deep);
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
}
.choice-btn.correct { border-color: var(--jade); background: var(--jade-soft); }
.choice-btn.correct .letter { background: var(--jade); color: #fff; }
.choice-btn.wrong { border-color: var(--danger); background: var(--danger-soft); opacity: 0.85; }
.choice-btn.wrong .letter { background: var(--danger); color: #fff; }
.choice-btn.dim { opacity: 0.45; }
.choice-btn:disabled { cursor: default; }

/* ---------- PLACEMENT (mountain climb) ---------- */
.climb-track {
  width: min(92vw, 560px);
  display: flex;
  align-items: center;
  gap: 4px;
  margin-bottom: 1vh;
}
.climb-bar {
  flex: 1;
  height: 12px;
  background: var(--card);
  border: 2px solid var(--border);
  border-radius: 999px;
  overflow: hidden;
}
.climb-fill {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--jade), var(--gold));
  border-radius: 999px;
  transition: width 0.6s ease;
}
.climb-peak { font-size: clamp(18px, 4vw, 26px); }
.age-cards {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: 1vh;
}
.age-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  width: clamp(120px, 27vw, 170px);
  background: var(--card);
  border: 3px solid var(--border);
  border-radius: 20px;
  padding: 20px 12px;
  cursor: pointer;
  font-size: clamp(15px, 2.8vw, 19px);
  font-weight: 800;
  color: var(--ink);
}
.age-card:active { transform: scale(0.95); border-color: var(--primary); }
.age-card .age-emoji { font-size: clamp(34px, 8vw, 52px); }
.age-card .age-sub { font-size: clamp(11px, 2vw, 13px); color: var(--muted); font-weight: 600; }

/* ---------- MILESTONE PATH (weekly + battle) ---------- */
.qm-milestone { width: min(94vw, 640px); margin-bottom: 8px; }
.ms-track {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  position: relative;
  padding: 6px 10px 12px;
}
.ms-track::before {
  content: "";
  position: absolute;
  left: 4%;
  right: 4%;
  bottom: 10px;
  height: 8px;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--jade-border), var(--gold), var(--primary));
}
.ms-node {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
}
.ms-startflag { font-size: clamp(18px, 4vw, 26px); padding-bottom: 4px; }
.ms-img { width: clamp(38px, 9vw, 62px); height: auto; display: block; opacity: 0.6; }
.ms-emoji { font-size: clamp(24px, 6vw, 40px); opacity: 0.6; }
.ms-day {
  font-size: clamp(9px, 1.7vw, 12px);
  font-weight: 800;
  color: var(--muted);
}
.ms-done .ms-img, .ms-done .ms-emoji { filter: none; opacity: 1; }
.ms-active .ms-img, .ms-active .ms-emoji { filter: none; opacity: 1; animation: msBounce 0.9s ease infinite; }
@keyframes msBounce {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-7px); }
}
.ms-final .ms-img { width: clamp(54px, 13vw, 88px); }
.ms-final .ms-emoji { font-size: clamp(34px, 8vw, 56px); }
.ms-check {
  position: absolute;
  top: -10px;
  right: -6px;
  font-size: clamp(13px, 2.6vw, 18px);
}
.ms-battle { margin-bottom: 4px; }
.ms-battle .ms-img { width: clamp(26px, 6vw, 40px); }
.ms-battle .ms-emoji { font-size: clamp(18px, 4vw, 26px); }
.ms-battle .ms-final .ms-img { width: clamp(36px, 8vw, 56px); }
.ms-battle .ms-track { padding: 2px 8px 8px; }
.ms-battle .ms-track::before { height: 5px; bottom: 7px; }

/* ---------- BATTLE MODE ---------- */
#battle-screen { padding-top: 2vh; position: relative; }
.arena {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 4vw;
  width: min(94vw, 640px);
  background: linear-gradient(var(--sky-top) 60%, var(--sky-ground) 60%);
  border: 3px solid var(--border);
  border-radius: 20px;
  padding: 14px 12px 52px;   /* room for the pinned potion button */
}
.arena-img { background-size: cover; background-position: center bottom; }
.arena-img .fighter-name,
.arena-img .vs-label {
  text-shadow: 0 1px 0 #fff, 0 -1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff;
}
.fighter {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
  width: clamp(110px, 34vw, 180px);
}
.fighter-name {
  font-size: clamp(12px, 2.2vw, 15px);
  font-weight: 800;
  color: var(--ink);
  white-space: nowrap;
}
.vs-label {
  font-size: clamp(18px, 4vw, 28px);
  font-weight: 800;
  color: var(--danger-deep);
  padding-bottom: 40px;
}
.sprite-holder { width: clamp(90px, 26vw, 150px); }
.sprite-holder svg, .sprite-img { width: 100%; height: auto; display: block; }
.boss-final .sprite-holder { width: clamp(130px, 36vw, 210px); }
.boss-final .fighter-name { color: var(--danger-deep); }
.hp-bar {
  width: 100%;
  height: 14px;
  background: var(--card);
  border: 2px solid var(--border);
  border-radius: 999px;
  overflow: hidden;
}
.hp-fill {
  height: 100%;
  width: 100%;
  background: var(--jade);
  border-radius: 999px;
  transition: width 0.4s ease;
}
.hp-fill.hp-mid { background: var(--warn); }
.hp-fill.hp-low { background: var(--danger); }
.flash-layer {
  position: absolute;
  inset: 0;
  border-radius: 16px;
  background: var(--danger);
  opacity: 0;
  pointer-events: none;
}
.flash-red { animation: redFlicker 0.5s ease; }
.flash-green { background: var(--jade) !important; animation: redFlicker 0.6s ease; }
.float-heal {
  position: absolute;
  top: 20%;
  left: 50%;
  transform: translateX(-50%);
  font-size: clamp(15px, 3vw, 20px);
  font-weight: 800;
  color: var(--jade-deep);
  text-shadow: 0 1px 0 #fff, 0 -1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff;
  pointer-events: none;
  z-index: 5;
  animation: floatUp 0.9s ease forwards;
}
@keyframes floatUp {
  0% { opacity: 0; transform: translate(-50%, 10px); }
  25% { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -34px); }
}
/* pinned below the sprite so it never lifts the player's column
   and knocks the two fighters onto different ground lines */
.potion-btn {
  position: absolute;
  bottom: -38px;
  left: 50%;
  transform: translateX(-50%);
  font-size: clamp(13px, 2.4vw, 16px);
  font-weight: 800;
  color: var(--heading);
  background: var(--primary-soft);
  border: 2px solid var(--primary-border);
  border-radius: 999px;
  padding: 5px 14px;
  cursor: pointer;
  white-space: nowrap;
}
.potion-btn:active { transform: translateX(-50%) scale(0.93); }
.potion-btn:disabled { opacity: 0.4; }
@keyframes redFlicker {
  0%, 100% { opacity: 0; }
  20% { opacity: 0.55; }
  40% { opacity: 0.1; }
  60% { opacity: 0.45; }
  80% { opacity: 0.1; }
}
.lunge-right { animation: lungeR 0.5s ease; }
@keyframes lungeR {
  0%, 100% { transform: translateX(0); }
  40% { transform: translateX(clamp(30px, 8vw, 60px)) scale(1.06); }
}
.lunge-left { animation: lungeL 0.5s ease; }
@keyframes lungeL {
  0%, 100% { transform: translateX(0); }
  40% { transform: translateX(calc(-1 * clamp(30px, 8vw, 60px))) scale(1.06); }
}
.shake { animation: shakeX 0.45s ease; }
@keyframes shakeX {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-7px) rotate(-2deg); }
  40% { transform: translateX(6px) rotate(2deg); }
  60% { transform: translateX(-5px); }
  80% { transform: translateX(4px); }
}
.boss-down .sprite-holder { transform: rotate(80deg) translateY(14px); opacity: 0.75; transition: all 0.9s ease; }
.celebrate { animation: heroJump 0.55s ease 4; }
@keyframes heroJump {
  0%, 100% { transform: translateY(0); }
  45% { transform: translateY(-26px) rotate(-3deg); }
}
.battle-question { margin: 1.6vh 0 1vh; }
.battle-choice { padding: 11px 16px; }
/* impact sparks — a flurry scatters them across the boss, and
   `left`/`top` are set inline per hit so no two land together */
.hit-star {
  position: absolute;
  font-size: clamp(22px, 5vw, 36px);
  z-index: 6;
  pointer-events: none;
  transform: translate(-50%, -50%);
  animation: hitPop 0.42s ease-out forwards;
}
.hit-star.hit-final {
  font-size: clamp(34px, 8vw, 56px);
  animation: hitPopBig 0.6s ease-out forwards;
}
@keyframes hitPop {
  0% { transform: translate(-50%, -50%) scale(0.3) rotate(-20deg); opacity: 0; }
  35% { transform: translate(-50%, -50%) scale(1.25) rotate(6deg); opacity: 1; }
  100% { transform: translate(-50%, -70%) scale(0.95); opacity: 0; }
}
@keyframes hitPopBig {
  0% { transform: translate(-50%, -50%) scale(0.2); opacity: 0; }
  30% { transform: translate(-50%, -50%) scale(1.55); opacity: 1; }
  60% { transform: translate(-50%, -50%) scale(1.2); opacity: 1; }
  100% { transform: translate(-50%, -80%) scale(1); opacity: 0; }
}

/* the finisher of a flurry hits noticeably harder than the taps */
.shake-hard { animation: shakeHard 0.42s ease; }
@keyframes shakeHard {
  0%, 100% { transform: translate(0, 0) rotate(0); }
  15% { transform: translate(-13px, 5px) rotate(-4deg); }
  30% { transform: translate(11px, -6px) rotate(4deg); }
  45% { transform: translate(-9px, 4px) rotate(-3deg); }
  60% { transform: translate(7px, -3px) rotate(2deg); }
  80% { transform: translate(-4px, 2px) rotate(-1deg); }
}

/* ---------- TYPED ANSWERS: THE KEYPAD ---------- */
.battle-pad {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  width: min(92vw, 340px);
}
.pad-display {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 2px;
  width: 100%;
  min-height: 62px;
  background: var(--card);
  border: 3px solid var(--border);
  border-radius: 16px;
  font-size: clamp(26px, 6vw, 38px);
  font-weight: 800;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  padding: 6px 14px;
}
.pad-display.pad-right { border-color: var(--jade); background: var(--jade-soft); }
.pad-display.pad-wrong { border-color: var(--danger); background: var(--danger-soft); }
.pad-answer { font-size: 0.62em; color: var(--jade-deep); font-weight: 800; }
.pad-caret {
  width: 3px;
  height: 1em;
  background: var(--primary);
  animation: caret 1s step-end infinite;
}
@keyframes caret { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }
.pad-display.pad-right .pad-caret,
.pad-display.pad-wrong .pad-caret { display: none; }

.pad-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  width: 100%;
}
.pad-extras { display: flex; gap: 8px; width: 100%; }
.pad-key {
  font-size: clamp(20px, 4.5vw, 27px);
  font-weight: 800;
  color: var(--ink);
  background: var(--card);
  border: 3px solid var(--border);
  border-radius: 14px;
  padding: 12px 0;
  cursor: pointer;
  transition: transform 0.08s, background 0.12s;
}
.pad-key:active { transform: scale(0.94); background: var(--primary-soft); }
.pad-key:disabled { opacity: 0.45; }
.pad-key.pad-del { color: var(--danger-deep); font-size: clamp(18px, 4vw, 23px); }
.pad-key.pad-x { flex: 1; color: var(--primary-deep); }
.pad-blank { visibility: hidden; }
.pad-go { margin-top: 2px; padding: 12px 40px; font-size: clamp(18px, 3.6vw, 24px); }

/* ---------- COMBO CHAIN ---------- */
.combo-badge {
  align-self: center;
  display: inline-flex;
  align-items: center;
  font-family: inherit;
  font-size: clamp(13px, 2.6vw, 17px);
  font-weight: 800;
  padding: 4px 14px;
  border-radius: 999px;
  margin-bottom: 4px;
  animation: comboPop 0.4s ease;
}
.combo-badge.combo-t2 { background: var(--jade-soft); color: var(--jade-deep); border: 2px solid var(--jade); }
.combo-badge.combo-t3 { background: var(--primary-soft); color: var(--primary-deep); border: 2px solid var(--primary); }
.combo-badge.combo-t4 {
  background: linear-gradient(90deg, var(--gold), var(--primary));
  color: #fff;
  border: 2px solid var(--gold-deep);
  animation: comboPop 0.4s ease, comboGlow 1s ease-in-out infinite;
}
@keyframes comboPop {
  0% { transform: scale(0.4); opacity: 0; }
  60% { transform: scale(1.18); opacity: 1; }
  100% { transform: scale(1); }
}
@keyframes comboGlow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(242, 193, 78, 0.7); }
  50% { box-shadow: 0 0 0 10px rgba(242, 193, 78, 0); }
}

/* ---------- ATTACK CUT-INS ---------- */
.attack-overlay {
  position: fixed;   /* the battle screen scrolls — the cut-in must not */
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 60;
  pointer-events: none;
  overflow: hidden;
}
.attack-overlay .atk-figure {
  width: clamp(150px, 44vw, 300px);
  height: auto;
  z-index: 2;
  filter: drop-shadow(0 0 18px var(--atk));
}
.attack-overlay .atk-avatar svg,
.attack-overlay .atk-avatar .avatar-rig { width: 100%; height: auto; }
.attack-overlay.playing .atk-figure { animation: atkIn 0.42s cubic-bezier(.2,1.5,.4,1); }
@keyframes atkIn {
  0% { transform: translateX(-45%) scale(0.6); opacity: 0; }
  60% { transform: translateX(6%) scale(1.14); opacity: 1; }
  100% { transform: translateX(0) scale(1); opacity: 1; }
}
.attack-overlay .atk-name {
  position: absolute;
  bottom: 12%;
  z-index: 3;
  font-size: clamp(20px, 5.5vw, 36px);
  font-weight: 800;
  color: #fff;
  letter-spacing: 0.02em;
  text-shadow: 0 2px 0 var(--atk), 0 0 18px var(--atk), 0 3px 10px rgba(0,0,0,.4);
}
.attack-overlay.playing .atk-name { animation: atkName 0.5s ease; }
@keyframes atkName {
  0% { transform: translateY(16px) scale(0.8); opacity: 0; }
  100% { transform: translateY(0) scale(1); opacity: 1; }
}

/* tier 1 — a single gold slash */
.fx-slash {
  position: absolute;
  top: 46%;
  left: -20%;
  width: 140%;
  height: 7px;
  background: linear-gradient(90deg, transparent, var(--atk), #fff, var(--atk), transparent);
  border-radius: 999px;
  transform: rotate(-16deg) scaleX(0);
  transform-origin: left center;
}
.attack-overlay.playing .fx-slash { animation: slash 0.42s ease-out; }
@keyframes slash {
  0% { transform: rotate(-16deg) scaleX(0); opacity: 0; }
  30% { opacity: 1; }
  70% { transform: rotate(-16deg) scaleX(1); opacity: 1; }
  100% { transform: rotate(-16deg) scaleX(1); opacity: 0; }
}

/* tier 2 — jade speed lines */
.fx-speed { position: absolute; inset: 0; }
.fx-speed i {
  position: absolute;
  left: -30%;
  height: 5px;
  width: 60%;
  border-radius: 999px;
  background: linear-gradient(90deg, transparent, var(--atk));
  opacity: 0;
}
.fx-speed i:nth-child(1) { top: 24%; }
.fx-speed i:nth-child(2) { top: 38%; height: 8px; }
.fx-speed i:nth-child(3) { top: 52%; }
.fx-speed i:nth-child(4) { top: 66%; height: 8px; }
.fx-speed i:nth-child(5) { top: 78%; }
.attack-overlay.playing .fx-speed i { animation: speedLine 0.55s ease-out; }
.attack-overlay.playing .fx-speed i:nth-child(2) { animation-delay: 0.06s; }
.attack-overlay.playing .fx-speed i:nth-child(3) { animation-delay: 0.03s; }
.attack-overlay.playing .fx-speed i:nth-child(4) { animation-delay: 0.09s; }
.attack-overlay.playing .fx-speed i:nth-child(5) { animation-delay: 0.12s; }
@keyframes speedLine {
  0% { transform: translateX(0); opacity: 0; }
  25% { opacity: 0.95; }
  100% { transform: translateX(190%); opacity: 0; }
}

/* tier 3 — bronze shockwave rings */
.fx-rings { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
.fx-rings i {
  position: absolute;
  width: 34%;
  aspect-ratio: 1;
  border: 6px solid var(--atk);
  border-radius: 50%;
  opacity: 0;
}
.attack-overlay.playing .fx-rings i { animation: ring 0.8s ease-out; }
.attack-overlay.playing .fx-rings i:nth-child(2) { animation-delay: 0.13s; }
.attack-overlay.playing .fx-rings i:nth-child(3) { animation-delay: 0.26s; }
@keyframes ring {
  0% { transform: scale(0.2); opacity: 0.9; border-width: 10px; }
  100% { transform: scale(3.2); opacity: 0; border-width: 1px; }
}

/* tier 4 — full-screen burst behind a turning mandala */
.attack-overlay.tier-4 { background: radial-gradient(circle at center, rgba(255,247,230,.92), rgba(242,169,59,.55) 55%, rgba(242,169,59,0) 78%); }
.fx-burst { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
.fx-mandala {
  position: absolute;
  width: 118%;
  aspect-ratio: 1;
  border-radius: 50%;
  background:
    repeating-conic-gradient(from 0deg, var(--atk) 0deg 5deg, transparent 5deg 16deg);
  opacity: 0;
  mask-image: radial-gradient(circle, transparent 26%, #000 34%, #000 62%, transparent 70%);
  -webkit-mask-image: radial-gradient(circle, transparent 26%, #000 34%, #000 62%, transparent 70%);
}
.fx-rays {
  position: absolute;
  width: 190%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: repeating-conic-gradient(from 12deg, rgba(255,255,255,.85) 0deg 3deg, transparent 3deg 22deg);
  opacity: 0;
}
.attack-overlay.playing .fx-mandala { animation: mandala 1.6s ease-out; }
.attack-overlay.playing .fx-rays { animation: rays 1.6s ease-out; }
@keyframes mandala {
  0% { transform: scale(0.2) rotate(0deg); opacity: 0; }
  25% { opacity: 0.95; }
  100% { transform: scale(1.5) rotate(150deg); opacity: 0; }
}
@keyframes rays {
  0% { transform: scale(0.3) rotate(0deg); opacity: 0; }
  20% { opacity: 0.7; }
  100% { transform: scale(1.4) rotate(-90deg); opacity: 0; }
}

.screen-shake { animation: screenShake 0.34s ease-in-out infinite; }
@keyframes screenShake {
  0%, 100% { transform: translate(0, 0); }
  25% { transform: translate(-5px, 3px); }
  50% { transform: translate(4px, -4px); }
  75% { transform: translate(-3px, -2px); }
}

@media (prefers-reduced-motion: reduce) {
  .attack-overlay * { animation: none !important; }
  .screen-shake { animation: none !important; }
  .combo-badge { animation: none !important; }
}

.countdown-overlay {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  background: var(--overlay);
  z-index: 20;
}
.countdown-num {
  font-size: clamp(70px, 18vw, 130px);
  font-weight: 800;
  color: #fff;
  text-shadow: 0 6px 0 rgba(0, 0, 0, 0.25);
}
.cd-pop { animation: cdPop 0.75s ease; }
@keyframes cdPop {
  0% { transform: scale(0.2); opacity: 0; }
  35% { transform: scale(1.25); opacity: 1; }
  70% { transform: scale(1); }
  100% { transform: scale(1); opacity: 0.9; }
}

.battle-result {
  position: absolute;
  inset: 0;
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  background: var(--overlay-paper);
  z-index: 15;
  padding: 20px;
  text-align: center;
}
.br-title { font-size: clamp(28px, 7vw, 46px); font-weight: 800; color: var(--heading); }
.br-time { font-size: clamp(17px, 3.4vw, 24px); font-weight: 800; color: var(--ink); }
.br-record { font-size: clamp(14px, 2.6vw, 18px); font-weight: 700; color: var(--jade-deep); max-width: 480px; line-height: 1.5; }

/* ---------- QUEST RESULT (XP breakdown) ---------- */
.xp-sheet {
  width: min(92vw, 480px);
  background: var(--card);
  border: 3px solid var(--border);
  border-radius: 20px;
  padding: 16px 20px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.xp-row {
  display: flex;
  justify-content: space-between;
  font-size: clamp(14px, 2.6vw, 17px);
  font-weight: 700;
  color: var(--ink);
}
.xp-row .xr-label { color: var(--muted); }
.xp-row.xp-total {
  border-top: 2px dashed var(--border);
  padding-top: 8px;
  font-weight: 800;
  font-size: clamp(16px, 3vw, 20px);
}
.xp-row.xp-total .xr-label { color: var(--heading); }
.xp-row .xr-val { color: var(--gold-deep); }
.mastery-note {
  font-size: clamp(13px, 2.4vw, 16px);
  font-weight: 800;
  color: var(--heading);
  background: var(--gold-soft);
  border: 2px solid var(--gold);
  border-radius: 12px;
  padding: 8px 16px;
  margin-top: 10px;
  text-align: center;
  max-width: 92vw;
}

/* ---------- STARS / CELEBRATION ---------- */
.stars { display: flex; gap: 14px; margin: 3vh 0; }
.star { font-size: clamp(44px, 10vw, 72px); filter: grayscale(1) opacity(0.3); transform: scale(0.7); transition: all 0.4s; }
.star.lit { filter: none; transform: scale(1); animation: starPop 0.5s ease; }
@keyframes starPop {
  0% { transform: scale(0.3) rotate(-30deg); }
  70% { transform: scale(1.25) rotate(8deg); }
  100% { transform: scale(1); }
}
.score-line { font-size: clamp(20px, 4vw, 30px); font-weight: 800; color: var(--ink); }

/* ---------- CONFETTI ---------- */
.confetti {
  position: fixed;
  top: -20px;
  width: 12px; height: 12px;
  border-radius: 3px;
  pointer-events: none;
  z-index: 50;
  animation: fall linear forwards;
}
@keyframes fall {
  to { transform: translateY(110vh) rotate(720deg); }
}

/* ---------- AVATAR EDITOR ----------
   Two panes: the monk on one side, the controls on the other.
   The old single-column stack put a horizontally scrolling tab
   strip above a scrolling grid, which collapsed on resize. */
#avatar-screen { padding: 2.5vh 3vw; }
.av-layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: 14px;
  width: 100%;
  max-width: 940px;
  align-items: start;
}
@media (min-width: 700px) {
  .av-layout { grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); gap: 26px; align-items: center; }
  .av-title { text-align: left; }
}
.av-stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.av-title { font-size: clamp(24px, 5vw, 40px); margin-bottom: 2px; }
.avatar-preview {
  width: clamp(150px, 34vw, 300px);
  max-width: 100%;
}
.avatar-preview svg,
.avatar-preview .avatar-rig { width: 100%; height: auto; display: block; }
.av-coins { font-size: clamp(14px, 2.6vw, 18px); padding: 6px 16px; }

.av-panel {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
  width: 100%;
}

/* tabs WRAP into a grid instead of scrolling sideways */
.avatar-tabs {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  width: 100%;
}
.avatar-tab {
  font-size: clamp(13px, 2.4vw, 17px);
  font-weight: 800;
  color: var(--primary-deep);
  background: var(--gold-soft);
  border: 2px solid var(--primary-border);
  border-radius: 14px;
  padding: 11px 6px;
  cursor: pointer;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.avatar-tab.selected {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}

.avatar-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 10px;
  width: 100%;
  max-height: 46vh;
  overflow-y: auto;
  padding: 4px;
  align-content: start;
}
.avatar-item {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  background: var(--card);
  border: 3px solid var(--border);
  border-radius: 16px;
  padding: 8px 6px;
  cursor: pointer;
  min-width: 0;
}
.avatar-item svg,
.avatar-item .avatar-rig { width: 100%; height: auto; }
.avatar-item .ai-name {
  font-size: clamp(10px, 1.9vw, 13px);
  font-weight: 700;
  color: var(--ink);
  text-align: center;
  line-height: 1.2;
}
.avatar-item.equipped { border-color: var(--jade); background: var(--jade-soft); }
.avatar-item.locked { opacity: 0.55; }
.avatar-item .ai-lock {
  font-size: clamp(9px, 1.7vw, 11px);
  font-weight: 800;
  color: var(--muted);
  text-align: center;
  line-height: 1.2;
}
.avatar-swatch {
  width: 100%;
  aspect-ratio: 1.5;
  border-radius: 10px;
  border: 2px solid var(--border);
}
.av-actions { margin-top: 10px; }

/* ---------- SETTINGS / PARENT ---------- */
.settings-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: min(92vw, 520px);
}
.setting-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  background: var(--card);
  border: 3px solid var(--border);
  border-radius: 16px;
  padding: 12px 16px;
  font-size: clamp(14px, 2.6vw, 17px);
  font-weight: 700;
  color: var(--ink);
}
.setting-row select {
  font-size: clamp(12px, 2.2vw, 14px);
  padding: 8px;
  border: 2px solid var(--border);
  border-radius: 10px;
  background: var(--paper);
  color: var(--ink);
  max-width: 55%;
}
.switch {
  position: relative;
  width: 56px; height: 32px;
  flex-shrink: 0;
  background: var(--border);
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.2s;
  border: none;
}
.switch::after {
  content: "";
  position: absolute;
  top: 4px; left: 4px;
  width: 24px; height: 24px;
  border-radius: 50%;
  background: #fff;
  transition: left 0.2s;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
}
.switch.on { background: var(--jade); }
.switch.on::after { left: 28px; }
.voices-note {
  font-size: clamp(12px, 2.2vw, 14px);
  color: var(--muted);
  text-align: center;
  max-width: 480px;
  line-height: 1.5;
}

/* ---------- ACCOUNT ---------- */
.acc-input {
  flex: 1;
  min-width: 0;
  font-size: clamp(15px, 2.8vw, 19px);
  font-weight: 700;
  color: var(--ink);
  border: 2px solid var(--border);
  border-radius: 10px;
  padding: 10px 12px;
  background: var(--paper);
}
.acc-pin { flex: 0 0 110px; text-align: center; letter-spacing: 6px; }

/* ---------- LEADERBOARD ---------- */
.lb-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: min(92vw, 560px);
  max-height: 48vh;
  overflow-y: auto;
}
.lb-row {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--card);
  border: 2px solid var(--border);
  border-radius: 12px;
  padding: 8px 12px;
  font-size: clamp(13px, 2.4vw, 16px);
  font-weight: 700;
  color: var(--ink);
}
.lb-row .lb-rank {
  flex-shrink: 0;
  width: 42px;
  text-align: center;
  font-weight: 800;
  color: var(--heading);
}
.lb-row .lb-ava { width: 34px; flex-shrink: 0; }
.lb-row .lb-ava svg { width: 100%; height: auto; display: block; }
.lb-row .lb-handle { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lb-row .lb-score { flex-shrink: 0; color: var(--muted); font-size: clamp(11px, 2vw, 13px); }
.lb-row.lb-me { border-color: var(--primary); background: var(--primary-soft); }
.lb-row.lb-top1 .lb-rank { color: var(--gold-deep); }

/* ---------- PARENTAL GATE ---------- */
.gate-question {
  font-size: clamp(26px, 6vw, 40px);
  font-weight: 800;
  color: var(--ink);
  margin: 2vh 0 1vh;
}
.gate-input {
  width: 140px;
  font-size: clamp(22px, 5vw, 32px);
  font-weight: 800;
  text-align: center;
  border: 3px solid var(--primary-border);
  border-radius: 14px;
  padding: 10px;
  background: var(--card);
  color: var(--ink);
}
.gate-error {
  color: var(--danger-deep);
  font-weight: 700;
  font-size: clamp(13px, 2.4vw, 16px);
  margin-top: 8px;
}

/* ---------- GENERIC NOTE BANNER ---------- */
.note-banner {
  font-size: clamp(13px, 2.4vw, 16px);
  font-weight: 800;
  color: var(--gold-deep);
  background: var(--gold-soft);
  border: 2px solid var(--gold);
  border-radius: 12px;
  padding: 8px 16px;
  margin-bottom: 10px;
  text-align: center;
  max-width: 92vw;
}

/* ---------- AVATAR RIG (stacked PNG layers) ---------- */
.avatar-rig { position: relative; width: 100%; aspect-ratio: 1 / 1; }
.avatar-rig .av-layer {
  position: absolute;
  height: auto;
  display: block;
  image-rendering: auto;
  pointer-events: none;
}
/* z-order: aura behind, front FX in front */
.avatar-rig .av-aura   { z-index: 0; }
.avatar-rig .av-body   { z-index: 1; }
.avatar-rig .av-hands  { z-index: 2; }
.avatar-rig .av-head   { z-index: 3; }
.avatar-rig .av-hair   { z-index: 4; }
.avatar-rig .av-gear   { z-index: 5; }
.avatar-rig .av-weapon { z-index: 6; }
.avatar-rig .av-fx     { z-index: 7; }
.avatar-rig .av-aura { animation: auraPulse 2.4s ease-in-out infinite; }

/* PNG poses: no limb rig, so the whole monk acts instead */
.avatar-rig.pose-attack   { transform: translateX(6%) rotate(-4deg); }
.avatar-rig.pose-hit      { transform: translateX(-4%) rotate(3deg); }
.avatar-rig.pose-victory  { transform: translateY(-4%) scale(1.04); }
.avatar-rig.pose-defeated { transform: rotate(-8deg); opacity: 0.7; }
.avatar-rig { transition: transform 0.2s ease; }

/* an SVG rig is its own element — don't give it a box */
svg.avatar-rig { aspect-ratio: auto; }

/* ---------- FALLBACK SVG MONK: POSES ---------- */
.avatar-svg .arm { transition: transform 0.18s ease; }
.avatar-svg .arm-r { transform-origin: 76px 66px; }
.avatar-svg .arm-l { transform-origin: 44px 66px; }
.avatar-svg.pose-attack .arm-r { transform: rotate(-80deg); }
.avatar-svg.pose-attack .arm-l { transform: rotate(20deg); }
.avatar-svg.pose-victory .arm-r { transform: rotate(-115deg) translate(6px, -4px); }
.avatar-svg.pose-victory .arm-l { transform: rotate(115deg) translate(-6px, -4px); }
.avatar-svg.pose-hit .arm-l { transform: rotate(-14deg); }
.avatar-svg.pose-hit .arm-r { transform: rotate(14deg); }
.avatar-svg .face { pointer-events: none; }
.avatar-svg.pose-victory .face-calm { display: none; }
.avatar-svg.pose-victory .face-happy { display: block !important; }
.avatar-svg.pose-hit .face-calm,
.avatar-svg.pose-defeated .face-calm { display: none; }
.avatar-svg.pose-hit .face-hurt,
.avatar-svg.pose-defeated .face-hurt { display: block !important; }
.avatar-svg.pose-defeated { opacity: 0.7; }
.avatar-svg .layer-aura circle { animation: auraPulse 2.4s ease-in-out infinite; }
@keyframes auraPulse {
  0%, 100% { opacity: 0.18; }
  50% { opacity: 0.38; }
}

/* ---------- AURAS AND FRONT FX (CSS, not art) ----------
   Every aura is one tint, --aura, set inline from CATALOG[].fill, plus
   six <i> particles the rule below arranges however that aura needs.
   Adding an aura is a catalog entry and a rule here — no image, no
   download, and it moves, which is the whole point of an aura. */
.avatar-rig .av-aura,
.avatar-rig .av-fx {
  height: 100%;
  /* Clipped to the monk's own box: a petal that drifts out of frame
     lands on whatever tile sits next to it in the editor grid. */
  overflow: hidden;
}
/* :where() so this contributes no specificity — otherwise the shared
   default here out-ranks every per-aura rule below and silently hides
   the particles they switch on. */
:where(.avatar-rig) :where(.av-aura, .av-fx) > i {
  position: absolute;
  display: none;            /* each aura switches on the ones it uses */
  border-radius: 50%;
  background: var(--aura);
}

/* Faint Glow — the first one earned, so it stays quiet */
.aura-faint {
  background: radial-gradient(circle at 50% 56%, var(--aura) 0%, transparent 58%);
  animation: auraPulse 2.8s ease-in-out infinite;
}

/* Golden Aura — the glow plus a slow wheel of rays behind the monk */
.aura-golden {
  background: radial-gradient(circle at 50% 56%, var(--aura) 0%, transparent 62%);
  animation: auraPulse 2.2s ease-in-out infinite;
}
.aura-golden > i:first-child {
  display: block;
  inset: 4%;
  border-radius: 50%;
  background: conic-gradient(from 0deg,
    transparent 0 10deg, var(--aura) 12deg 15deg,
    transparent 17deg 55deg, var(--aura) 57deg 60deg,
    transparent 62deg 100deg, var(--aura) 102deg 105deg,
    transparent 107deg 145deg, var(--aura) 147deg 150deg,
    transparent 152deg 190deg, var(--aura) 192deg 195deg,
    transparent 197deg 235deg, var(--aura) 237deg 240deg,
    transparent 242deg 280deg, var(--aura) 282deg 285deg,
    transparent 287deg 325deg, var(--aura) 327deg 330deg,
    transparent 332deg 360deg);
  opacity: 0.45;
  animation: auraSpin 14s linear infinite;
}

/* Jade Flame — tongues licking up from the monk's feet */
.aura-jade {
  background: radial-gradient(circle at 50% 66%, var(--aura) 0%, transparent 52%);
  animation: auraPulse 1.6s ease-in-out infinite;
}
.aura-jade > i {
  display: block;
  width: 13%; height: 30%;
  bottom: 10%;
  border-radius: 50% 50% 42% 42% / 68% 68% 32% 32%;
  filter: blur(2px);
  opacity: 0.55;
  animation: auraFlame 1.5s ease-in-out infinite;
}
.aura-jade > i:nth-child(1) { left: 30%; animation-delay: 0s;    height: 26%; }
.aura-jade > i:nth-child(2) { left: 43%; animation-delay: -0.5s; height: 34%; }
.aura-jade > i:nth-child(3) { left: 57%; animation-delay: -0.9s; height: 28%; }
.aura-jade > i:nth-child(4) { left: 22%; animation-delay: -1.2s; height: 20%; opacity: 0.35; }
.aura-jade > i:nth-child(5) { left: 68%; animation-delay: -0.3s; height: 22%; opacity: 0.35; }
.aura-jade > i:nth-child(6) { display: none; }

/* Lotus Petals — petals rising and turning as they go.
   The tint lives on ::before so that dimming the glow does not also
   dim the petals in front of it. */
.aura-lotus::before {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(circle at 50% 58%, var(--aura) 0%, transparent 55%);
  opacity: 0.42;
}
.aura-lotus > i {
  display: block;
  width: 9%; height: 13%;
  border-radius: 50% 8% 50% 8%;
  top: 0;
  opacity: 0.85;
  animation: auraRise 4.2s linear infinite;
}
.aura-lotus > i:nth-child(1) { left: 14%; animation-delay: 0s; }
.aura-lotus > i:nth-child(2) { left: 30%; animation-delay: -0.9s; }
.aura-lotus > i:nth-child(3) { left: 52%; animation-delay: -1.8s; }
.aura-lotus > i:nth-child(4) { left: 70%; animation-delay: -2.6s; }
.aura-lotus > i:nth-child(5) { left: 84%; animation-delay: -3.4s; }
.aura-lotus > i:nth-child(6) { left: 44%; animation-delay: -2.1s; }

/* Sakura Swirl — the same petals, but circling the monk instead */
.aura-sakura::before {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(circle at 50% 58%, var(--aura) 0%, transparent 52%);
  opacity: 0.4;
}
.aura-sakura > i {
  display: block;
  width: 8%; height: 11%;
  left: 46%; top: 44%;
  border-radius: 50% 8% 50% 8%;
  opacity: 0.8;
  transform-origin: 50% 50%;
  animation: auraSwirl 5s linear infinite;
}
.aura-sakura > i:nth-child(1) { animation-delay: 0s; }
.aura-sakura > i:nth-child(2) { animation-delay: -0.83s; }
.aura-sakura > i:nth-child(3) { animation-delay: -1.66s; }
.aura-sakura > i:nth-child(4) { animation-delay: -2.5s; }
.aura-sakura > i:nth-child(5) { animation-delay: -3.33s; }
.aura-sakura > i:nth-child(6) { animation-delay: -4.16s; }

/* Starlight — points that twinkle in place rather than travel */
.aura-star::before {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(circle at 50% 54%, var(--aura) 0%, transparent 60%);
  opacity: 0.34;
}
.aura-star > i {
  display: block;
  width: 5%; height: 5%;
  border-radius: 0;
  clip-path: polygon(50% 0%, 61% 39%, 100% 50%, 61% 61%, 50% 100%, 39% 61%, 0% 50%, 39% 39%);
  animation: auraTwinkle 2.6s ease-in-out infinite;
}
.aura-star > i:nth-child(1) { left: 16%; top: 22%; animation-delay: 0s; }
.aura-star > i:nth-child(2) { left: 78%; top: 30%; animation-delay: -0.6s; }
.aura-star > i:nth-child(3) { left: 26%; top: 62%; animation-delay: -1.1s; }
.aura-star > i:nth-child(4) { left: 70%; top: 70%; animation-delay: -1.7s; }
.aura-star > i:nth-child(5) { left: 50%; top: 12%; animation-delay: -2.2s; width: 7%; height: 7%; }
.aura-star > i:nth-child(6) { left: 8%;  top: 46%; animation-delay: -0.3s; width: 3.5%; height: 3.5%; }

/* Drifting Petals — the one FX layer, and the only one in FRONT */
.fx-petals { opacity: 0.9; }
.fx-petals > i {
  display: block;
  width: 7%; height: 10%;
  border-radius: 50% 8% 50% 8%;
  top: 0;
  opacity: 0.9;
  animation: fxFall 5.5s linear infinite;
}
.fx-petals > i:nth-child(1) { left: 10%; animation-delay: 0s; }
.fx-petals > i:nth-child(2) { left: 28%; animation-delay: -1.2s; }
.fx-petals > i:nth-child(3) { left: 48%; animation-delay: -2.3s; }
.fx-petals > i:nth-child(4) { left: 66%; animation-delay: -3.4s; }
.fx-petals > i:nth-child(5) { left: 84%; animation-delay: -4.5s; }
.fx-petals > i:nth-child(6) { left: 38%; animation-delay: -0.7s; }

/* Lightning — bolts, not blobs, so the particles get a jagged clip and
   snap on and off instead of fading. Electricity that eases in and out
   reads as a glow; the sharp cut is what makes it read as a spark. */
.fx-spark > i {
  display: block;
  width: 13%; height: 30%;
  border-radius: 0;
  clip-path: polygon(52% 0%, 24% 46%, 45% 46%, 30% 100%, 76% 40%, 52% 40%, 72% 0%);
  filter: drop-shadow(0 0 5px var(--aura));
  opacity: 0;
  animation: fxSpark 1.4s steps(1, end) infinite;
}
/* Bolts crackle AROUND the monk, never across the face — an effect
   that covers the eyes stops being decoration and starts being damage. */
.fx-spark > i:nth-child(1) { left:  6%; top: 14%; animation-delay: 0s; }
.fx-spark > i:nth-child(2) { left: 81%; top: 20%; animation-delay: -0.23s; transform: scaleX(-1); }
.fx-spark > i:nth-child(3) { left: 14%; top: 48%; animation-delay: -0.47s; }
.fx-spark > i:nth-child(4) { left: 77%; top: 54%; animation-delay: -0.70s; transform: scaleX(-1); }
.fx-spark > i:nth-child(5) { left: 45%; top: -13%; animation-delay: -0.93s; width: 11%; height: 24%; }
.fx-spark > i:nth-child(6) { left:  0%; top: 32%; animation-delay: -1.16s; width: 9%; height: 20%; }

@keyframes fxSpark {
  0%   { opacity: 0.95; }
  10%  { opacity: 0; }
  16%  { opacity: 0.8; }
  24%  { opacity: 0; }
  100% { opacity: 0; }
}

@keyframes auraSpin  { to { transform: rotate(360deg); } }
@keyframes auraFlame {
  0%, 100% { transform: scaleY(1)    translateY(0);    opacity: 0.55; }
  50%      { transform: scaleY(1.35) translateY(-8%);  opacity: 0.3; }
}
/* A translate in % is a percentage of the ELEMENT, not of the avatar
   box it sits in. A petal 13% of the box tall needs translateY(-600%)
   to cross the monk, not -80%. Every distance below is in element
   widths, which is why the numbers look enormous. */
@keyframes auraRise {
  0%   { transform: translateY(620%)  rotate(0deg);   opacity: 0; }
  14%  { opacity: 0.85; }
  86%  { opacity: 0.5; }
  100% { transform: translateY(30%)   rotate(240deg); opacity: 0; }
}
@keyframes auraSwirl {
  0%   { transform: rotate(0deg)   translateX(340%) rotate(0deg); }
  100% { transform: rotate(360deg) translateX(340%) rotate(-360deg); }
}
@keyframes auraTwinkle {
  0%, 100% { opacity: 0.15; transform: scale(0.7); }
  50%      { opacity: 0.95; transform: scale(1.15); }
}
@keyframes fxFall {
  0%   { transform: translateY(-140%)  rotate(0deg);   opacity: 0; }
  12%  { opacity: 0.9; }
  88%  { opacity: 0.65; }
  100% { transform: translateY(1080%)  rotate(320deg); opacity: 0; }
}

/* Sensei's mouth can't animate on a PNG head — nod instead */
.avatar-rig.speaking .av-head { animation: talkNod 0.5s ease-in-out infinite; }
@keyframes talkNod {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(1.2%); }
}

/* ---------- SHOP ---------- */
.shop-hero { width: clamp(120px, 22vh, 180px); margin: 0 auto 1vh; }
.shop-hero svg, .shop-hero .avatar-rig { width: 100%; height: auto; display: block; }
.shop-name {
  font-size: clamp(20px, 4vw, 28px);
  font-weight: 800;
  color: var(--ink);
  text-align: center;
}
.shop-blurb {
  font-size: clamp(13px, 2.4vw, 16px);
  color: var(--muted);
  text-align: center;
  font-weight: 600;
  margin-top: 4px;
}
.shop-price {
  font-size: clamp(24px, 5vw, 34px);
  font-weight: 800;
  color: var(--gold-deep);
  text-align: center;
  margin: 1.5vh 0;
}
.shop-note {
  font-size: clamp(12px, 2.2vw, 14px);
  color: var(--muted);
  text-align: center;
  max-width: 420px;
  line-height: 1.5;
  margin: 0 auto;
}
/* For sale = try it on. A dashed edge says "not yours yet" without
   stopping anyone wearing it to see how it looks. */
.avatar-item.for-sale { border-style: dashed; }
/* worn but not paid for — the tile the bill is counting */
.avatar-item.previewing {
  border-color: var(--gold);
  border-style: dashed;
  background: var(--gold-soft);
}

/* ---------- the bill ---------- */
.av-bill {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
  margin: 1vh auto 0;
  padding: 8px 16px;
  max-width: 560px;
  background: var(--gold-soft);
  border: 2px solid var(--gold);
  border-radius: 16px;
}
.av-bill-text {
  font-weight: 700;
  color: var(--gold-deep);
  font-size: clamp(13px, 2.6vw, 15px);
}
.av-bill-btn { margin: 0; }

/* the basket list on the confirm screen */
.basket-list { list-style: none; margin: 0 0 1.5vh; padding: 0; text-align: left; }
.basket-list li {
  display: flex; justify-content: space-between; gap: 12px;
  padding: 7px 2px; border-bottom: 1px dashed var(--sand-line, #E0D6C0);
  font-size: clamp(13px, 2.7vw, 15px);
}
.basket-list li:last-child { border-bottom: none; }
.basket-total {
  display: flex; justify-content: space-between; gap: 12px;
  font-weight: 800; padding: 8px 2px 0; color: var(--gold-deep);
}
.ai-lock.ai-price {
  color: var(--gold-deep);
  background: var(--gold-soft);
  border-radius: 999px;
  padding: 1px 8px;
  font-weight: 800;
}

/* ---------- CHARACTER ANIMATION ---------- */
.char-svg { display: block; }
.spark { opacity: 0; }
.speaking .spark.s1 { animation: twinkle 1.1s infinite; }
.speaking .spark.s2 { animation: twinkle 1.4s 0.4s infinite; }
@keyframes twinkle { 0%, 100% { opacity: 0; } 50% { opacity: 1; } }
.bobbing { animation: bob 2.2s ease-in-out infinite; }
@keyframes bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-7px); }
}

/* ============================================================
   BREATHING, BATTLE STANCE AND TRANSFORMATIONS
   ============================================================ */

/* ---------- breathing ----------
   Only ever on the idle pose: the pose classes drive `transform`
   too, and a lunging monk should not also be calmly breathing. */
.avatar-rig.pose-idle,
svg.avatar-rig.pose-idle {
  animation: breathe 3.6s ease-in-out infinite;
}
@keyframes breathe {
  0%, 100% { transform: translateY(0) scale(1); }
  50%      { transform: translateY(-1%) scale(1.014); }
}

/* ---------- battle stance ----------
   A fighter waits leaning in, weight low, breathing faster —
   no new art needed, just a different resting transform. */
.avatar-rig.stance-battle.pose-idle,
svg.avatar-rig.stance-battle.pose-idle {
  animation: breatheBattle 1.7s ease-in-out infinite;
}
@keyframes breatheBattle {
  0%, 100% { transform: translateY(0) rotate(-3deg) scale(1, 0.995); }
  50%      { transform: translateY(-1.8%) rotate(-3deg) scale(1.02, 1.015); }
}
/* The weapon layer is a near-full-frame image, so rotating it in
   place swings the pole across the monk's face. Leave it upright
   at rest and only move it during a strike. */
.avatar-rig .av-weapon { transform-origin: 74% 72%; }

/* tier 1 — the player's own monk, so the staff itself does the work */
.avatar-rig.pose-attack .av-weapon { animation: wpnThrust 0.55s ease; }
@keyframes wpnThrust {
  0%   { transform: rotate(0deg) translate(0, 0); }
  25%  { transform: rotate(-38deg) translate(-4%, -3%); }
  55%  { transform: rotate(26deg) translate(9%, 2%); }
  75%  { transform: rotate(10deg) translate(4%, 0); }
  100% { transform: rotate(0deg) translate(0, 0); }
}

/* ---------- transformed fighter ---------- */
.sprite-holder.transformed { width: clamp(120px, 34vw, 190px); }
.sprite-holder .form-img {
  width: 100%;
  height: auto;
  display: block;
  animation: formIn 0.32s cubic-bezier(.2, 1.6, .4, 1);
  filter: drop-shadow(0 0 10px rgba(255, 214, 130, 0.55));
}
@keyframes formIn {
  0% { transform: scale(0.55) translateY(12%); opacity: 0; }
  70% { transform: scale(1.1) translateY(0); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

/* ---------- transformation puff ---------- */
.form-puff {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 8;
}
.form-puff i {
  position: absolute;
  left: 50%;
  top: 55%;
  width: 46%;
  aspect-ratio: 1;
  border-radius: 50%;
  transform: translate(-50%, -50%) scale(0.2);
  opacity: 0;
  animation: puffOut 0.7s ease-out forwards;
}
.form-puff i:nth-child(2) { animation-delay: 0.05s; left: 32%; top: 44%; width: 36%; }
.form-puff i:nth-child(3) { animation-delay: 0.09s; left: 68%; top: 48%; width: 34%; }
.form-puff i:nth-child(4) { animation-delay: 0.14s; left: 42%; top: 70%; width: 32%; }
.form-puff i:nth-child(5) { animation-delay: 0.18s; left: 60%; top: 30%; width: 30%; }

/* black smoke for the ninja */
.puff-smoke i {
  background: radial-gradient(circle at 40% 38%, #6A6A72 0%, #33333B 55%, rgba(28, 28, 34, 0) 72%);
}
/* warm light for the guardian and the radiant form */
.puff-light i {
  background: radial-gradient(circle at 45% 40%, #FFF6E0 0%, #F2C14E 45%, rgba(242, 169, 59, 0) 72%);
}
@keyframes puffOut {
  0% { transform: translate(-50%, -50%) scale(0.2); opacity: 0; }
  25% { opacity: 0.95; }
  100% { transform: translate(-50%, -78%) scale(1.5); opacity: 0; }
}

/* ---------- tier 2 cut-in smoke ---------- */
.fx-smoke { position: absolute; inset: 0; }
.fx-smoke i {
  position: absolute;
  bottom: 18%;
  width: 30%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle at 42% 40%, #6A6A72 0%, #2E2E36 55%, rgba(24, 24, 30, 0) 73%);
  opacity: 0;
  transform: scale(0.3);
}
.fx-smoke i:nth-child(1) { left: 6%; }
.fx-smoke i:nth-child(2) { left: 24%; bottom: 34%; width: 34%; }
.fx-smoke i:nth-child(3) { left: 44%; bottom: 12%; width: 28%; }
.fx-smoke i:nth-child(4) { left: 60%; bottom: 40%; width: 32%; }
.fx-smoke i:nth-child(5) { left: 74%; bottom: 20%; width: 26%; }
.fx-smoke i:nth-child(6) { left: 34%; bottom: 55%; width: 24%; }
.attack-overlay.playing .fx-smoke i { animation: smokeRise 1s ease-out forwards; }
.attack-overlay.playing .fx-smoke i:nth-child(2) { animation-delay: 0.05s; }
.attack-overlay.playing .fx-smoke i:nth-child(3) { animation-delay: 0.1s; }
.attack-overlay.playing .fx-smoke i:nth-child(4) { animation-delay: 0.14s; }
.attack-overlay.playing .fx-smoke i:nth-child(5) { animation-delay: 0.19s; }
.attack-overlay.playing .fx-smoke i:nth-child(6) { animation-delay: 0.24s; }
@keyframes smokeRise {
  0% { transform: scale(0.3) translateY(0); opacity: 0; }
  22% { opacity: 0.9; }
  100% { transform: scale(1.7) translateY(-46%); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .avatar-rig.pose-idle,
  svg.avatar-rig.pose-idle,
  .avatar-rig.stance-battle.pose-idle,
  .form-puff i,
  .fx-smoke i,
  .sprite-holder .form-img { animation: none !important; }
}

/* ---------- transformed fighter: a distinct motion per tier ---------- */
.sprite-holder.transformed.striking.form-t2 .form-img { animation: formDash 0.62s cubic-bezier(.3,1.4,.4,1); }
.sprite-holder.transformed.striking.form-t3 .form-img { animation: formSlam 0.62s ease-in-out; }
.sprite-holder.transformed.striking.form-t4 .form-img { animation: formBurst 0.9s ease-out; }

/* ninja: darts in and back, twice */
@keyframes formDash {
  0%   { transform: translateX(0) scale(1); }
  22%  { transform: translateX(26%) scale(1.06); }
  40%  { transform: translateX(-6%) scale(0.98); }
  62%  { transform: translateX(22%) scale(1.05); }
  100% { transform: translateX(0) scale(1); }
}
/* guardian: rears back, then drives down */
@keyframes formSlam {
  0%   { transform: translateY(0) rotate(0deg); }
  30%  { transform: translateY(-14%) rotate(-8deg) scale(1.05); }
  55%  { transform: translateY(6%) rotate(6deg) scale(1.04); }
  70%  { transform: translateY(2%) rotate(2deg); }
  100% { transform: translateY(0) rotate(0deg); }
}
/* radiant: swells and pulses light outward */
@keyframes formBurst {
  0%   { transform: scale(1); filter: drop-shadow(0 0 10px rgba(255,214,130,.55)); }
  35%  { transform: scale(1.16); filter: drop-shadow(0 0 34px rgba(255,214,130,1)); }
  60%  { transform: scale(1.06); filter: drop-shadow(0 0 20px rgba(255,214,130,.8)); }
  100% { transform: scale(1); filter: drop-shadow(0 0 10px rgba(255,214,130,.55)); }
}

/* ---------- battle stance: turn to face the opponent ----------
   Real fighting-stance art (body_*_battle.png) replaces this when
   it exists; until then a slight turn beats standing to attention. */
.avatar-rig.stance-battle.pose-idle,
svg.avatar-rig.stance-battle.pose-idle {
  animation: breatheBattle 1.7s ease-in-out infinite;
}
@keyframes breatheBattle {
  0%, 100% { transform: perspective(700px) rotateY(-14deg) rotate(-2deg) translateY(0); }
  50%      { transform: perspective(700px) rotateY(-14deg) rotate(-2deg) translateY(-1.8%) scale(1.018); }
}

@media (prefers-reduced-motion: reduce) {
  .sprite-holder .form-img,
  .avatar-rig.pose-attack .av-weapon { animation: none !important; }
  /* Auras hold still rather than vanish — a player who paid for one
     should still see it, just not moving. */
  .avatar-rig .av-aura,
  .avatar-rig .av-fx,
  .avatar-rig .av-aura > i,
  .avatar-rig .av-fx > i { animation: none !important; opacity: 0.5; }
  .aura-lotus > i, .fx-petals > i { transform: translateY(300%); }
  .fx-spark > i { opacity: 0.7; }
}

/* ---------- SISTER APP ---------- */
/* Quiet on purpose. It sits under the week path, below everything a
   child came here to do, so it never competes with the Daily Quest. */
.sister-card {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  width: min(94vw, 640px);
  margin: 2vh auto 0;
  padding: 12px 14px;
  background: var(--card);
  border: 2px dashed var(--border);
  border-radius: 16px;
  text-decoration: none;
  color: inherit;
}
.sister-card:hover { border-color: var(--jade); background: var(--jade-soft); }
.sister-emoji { font-size: 26px; line-height: 1.1; flex-shrink: 0; }
.sister-text { display: flex; flex-direction: column; gap: 3px; }
.sister-text b { font-size: clamp(13px, 2.6vw, 15px); color: var(--ink); }
.sister-text small {
  font-size: clamp(11px, 2.2vw, 13px);
  font-weight: 600;
  color: var(--muted);
  line-height: 1.45;
}
.sister-text em {
  font-style: normal;
  font-weight: 800;
  font-size: clamp(11px, 2.2vw, 13px);
  color: var(--jade-solid);
}

/* ---------- ACCESS ---------- */
.days-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: clamp(12px, 2.3vw, 15px);
  font-weight: 800;
  color: var(--jade-solid);
  background: var(--jade-soft);
  border: 2px solid var(--jade);
  border-radius: 999px;
  padding: 4px 12px;
}
/* running out is a nudge, not an alarm — the child did nothing wrong */
.days-chip.low { color: var(--gold-deep); background: var(--gold-soft); border-color: var(--gold); }
.days-chip.out { color: var(--cinnabar); background: var(--cinnabar-lo); border-color: var(--cinnabar); }

.how-it-works { align-items: flex-start; }
.how-body {
  font-weight: 600;
  color: var(--muted);
  font-size: clamp(12px, 2.3vw, 14px);
  line-height: 1.5;
  margin-top: 6px;
}
.how-body p { margin: 0 0 8px; }
.how-body b { color: var(--ink); }
.how-cost { color: var(--jade-solid) !important; }
.how-warn {
  color: var(--gold-deep) !important;
  background: var(--gold-soft);
  border-radius: 10px;
  padding: 7px 10px;
}

/* ---------- COINS ---------- */
.coin-badge {
  display: inline-flex;
  align-items: center;
  font-size: clamp(12px, 2.3vw, 15px);
  font-weight: 800;
  color: var(--gold-deep);
  background: var(--gold-soft);
  border: 2px solid var(--gold);
  border-radius: 999px;
  padding: 4px 12px;
  flex-shrink: 0;
  cursor: pointer;
  white-space: nowrap;
}
.coin-badge:active { transform: scale(0.95); }
.shop-balance { text-align: center; margin-bottom: 1vh; }
.shop-short {
  font-size: clamp(13px, 2.4vw, 16px);
  font-weight: 800;
  color: var(--danger-deep);
  text-align: center;
  margin: 1vh 0;
}

/* ---------- COIN PACKS ---------- */
.pack-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  width: min(94vw, 560px);
}
.pack-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  width: clamp(130px, 40vw, 165px);
  background: var(--card);
  border: 3px solid var(--border);
  border-radius: 20px;
  padding: 18px 12px 14px;
  cursor: pointer;
}
.pack-card:active { transform: scale(0.96); }
.pack-card.best { border-color: var(--gold); background: var(--gold-soft); }
.pack-badge {
  position: absolute;
  top: -11px;
  background: var(--gold);
  color: var(--ink);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .04em;
  padding: 3px 10px;
  border-radius: 999px;
}
.pack-coins { font-size: clamp(20px, 4.4vw, 27px); font-weight: 800; color: var(--gold-deep); }
.pack-name { font-size: clamp(13px, 2.4vw, 16px); font-weight: 800; color: var(--ink); }
.pack-bonus { font-size: clamp(11px, 2vw, 13px); font-weight: 700; color: var(--jade-deep); }
.pack-price { font-size: clamp(15px, 3vw, 19px); font-weight: 800; color: var(--heading); margin-top: 4px; }

/* ---------- PAYMENT ORDER ---------- */
.order-box {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  width: min(94vw, 420px);
  background: var(--card);
  border: 3px solid var(--border);
  border-radius: 20px;
  padding: 20px 18px;
  text-align: center;
}
.order-amount { font-size: clamp(26px, 6vw, 38px); font-weight: 800; color: var(--heading); }
.order-coins { font-size: clamp(16px, 3vw, 21px); font-weight: 800; color: var(--gold-deep); }
/* The code now carries the whole payment card — payee, masked number
   and the amount — so it needs to be big enough to READ, not just big
   enough to scan. A parent about to send money checks the name first. */
.order-qr {
  width: clamp(210px, 62vw, 290px);
  height: auto;
  border-radius: 14px;
  border: 3px solid var(--border);
  margin: 8px 0;
  background: #fff;
}
/* the PayPal hand-off is an <a>, so it needs the button box itself */
.order-payee {
  font-size: clamp(12px, 2.2vw, 14px);
  color: var(--ink-soft, #6b5f4a);
  margin: 2px 0 6px;
  max-width: 34ch;
}
a.order-pay {
  display: inline-block;
  text-decoration: none;
  margin: 6px 0 2px;
}
.order-how {
  font-size: clamp(13px, 2.4vw, 15px);
  color: var(--muted);
  line-height: 1.5;
  font-weight: 600;
}
.order-ref-label {
  font-size: clamp(11px, 2vw, 13px);
  font-weight: 800;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .06em;
  margin-top: 8px;
}
.order-ref {
  font-family: "Courier New", monospace;
  font-size: clamp(18px, 4vw, 26px);
  font-weight: 800;
  color: var(--ink);
  background: var(--primary-soft);
  border: 2px dashed var(--primary);
  border-radius: 12px;
  padding: 8px 18px;
  letter-spacing: .08em;
  user-select: all;
  -webkit-user-select: all;
}
.order-wait {
  font-size: clamp(12px, 2.2vw, 14px);
  color: var(--muted);
  font-weight: 600;
  margin-top: 10px;
}

/* ---------- INSTALL CARD (Dojo) ---------- */
.install-card {
  display: flex;
  align-items: center;
  gap: 12px;
  width: min(92vw, 560px);
  margin-top: 10px;
  background: var(--gold-soft);
  border: 3px solid var(--gold);
  border-radius: 18px;
  padding: 12px 14px;
}
.install-card .ic-icon { font-size: clamp(24px, 5vw, 32px); flex-shrink: 0; }
.install-card .ic-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.install-card .ic-text b {
  font-size: clamp(14px, 2.7vw, 17px);
  font-weight: 800;
  color: var(--ink);
}
.install-card .ic-text small {
  font-size: clamp(11px, 2.1vw, 13px);
  color: var(--muted);
  font-weight: 600;
}
.install-card .ic-btn {
  flex-shrink: 0;
  font-size: clamp(13px, 2.4vw, 16px);
  font-weight: 800;
  color: #fff;
  background: var(--primary);
  border: none;
  border-radius: 999px;
  padding: 9px 20px;
  cursor: pointer;
  box-shadow: 0 3px 0 var(--primary-deep);
}
.install-card .ic-btn:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--primary-deep); }
.install-card .ic-x {
  flex-shrink: 0;
  background: none;
  border: none;
  color: var(--muted);
  font-size: 17px;
  font-weight: 800;
  cursor: pointer;
  padding: 4px 6px;
}

/* ---------- RECOVERY CODE ---------- */
.recovery-box {
  width: min(92vw, 480px);
  margin: 0 auto 1.5vh;
  background: var(--card);
  border: 3px solid var(--border);
  border-radius: 18px;
  padding: 16px;
  text-align: center;
}
.rec-label {
  font-family: inherit;
  font-size: clamp(11px, 2.1vw, 13px);
  font-weight: 800;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 6px;
}
.rec-note {
  font-size: clamp(12px, 2.3vw, 14.5px);
  color: var(--muted);
  font-weight: 600;
  line-height: 1.5;
  max-width: 40ch;
  margin: 0 auto;
}
.rec-code {
  font-family: "Courier New", monospace;
  font-size: clamp(15px, 3.4vw, 22px);
  font-weight: 800;
  color: var(--ink);
  background: var(--primary-soft);
  border: 2px dashed var(--primary);
  border-radius: 12px;
  padding: 10px 12px;
  margin-top: 12px;
  letter-spacing: .04em;
  user-select: all;
  -webkit-user-select: all;
  word-break: break-all;
}

/* Well clear of the Begin button — it sat close enough to be
   mistaken for part of it, and to be tapped by accident. */
.install-card-title { margin-top: clamp(34px, 8vh, 72px); }

/* ============================================================
   THE ARENA WEATHER
   ------------------------------------------------------------
   A miss streak turns the sky against the player. Two wrong in a
   row and the light goes out of the arena; three and it rains;
   four and it comes down hard with lightning. Every right answer
   walks it back one step, so the way out is always visible.

   Deliberately NOT tied to HP: health is already a bar, and a
   second bar in weather form would be noise. This tracks the run
   of mistakes, which is the thing a child can feel but cannot see.
   ============================================================ */

.arena { position: relative; }

.weather {
  position: absolute;
  inset: 0;
  border-radius: 17px;      /* the arena's 20px less its 3px border */
  overflow: hidden;         /* rain must not fall past the frame */
  pointer-events: none;
  z-index: 3;
}
.weather > * { position: absolute; }

/* The potion button lives inside a fighter and has to stay bright
   and tappable while the arena darkens around it. */
.potion-btn { z-index: 6; }

/* The hit flashes are feedback, not scenery: they have to read
   through the storm rather than be dimmed by it. */
.flash-layer { z-index: 4; }

/* ---------- the light goes ---------- */
.wx-dark {
  inset: 0;
  background: linear-gradient(rgba(20, 26, 48, 0.95), rgba(28, 34, 56, 0.6));
  opacity: 0;
  transition: opacity 1.1s ease;
}
/* Dusk, not night. The child still has to read four answer buttons
   and two health bars through this. The sky darkens harder than the
   ground, which is how weather actually arrives. */
.storm-1 .wx-dark { opacity: 0.32; }
.storm-2 .wx-dark { opacity: 0.52; }
.storm-3 .wx-dark { opacity: 0.72; }

/* ---------- rain ----------
   Stripes rather than particles: a hundred divs falling at 60fps on
   a cheap tablet is exactly the kind of thing that turns a battle
   into a slideshow. Two sheets at different speeds carry the depth. */
.wx-rain {
  inset: -30% -20%;
  opacity: 0;
  transition: opacity 0.9s ease;
  background-image: repeating-linear-gradient(
    110deg,
    rgba(214, 234, 255, 0) 0 13px,
    rgba(214, 234, 255, 0.5) 13px 14px,
    rgba(214, 234, 255, 0) 14px 27px
  );
  /* The tile is what breaks the lines into falling streaks — a
     continuous line sliding along its own length looks like nothing
     at all. Tall and narrow, so the streaks are long and the pattern
     does not read as a grid. */
  background-size: 110px 300px;
  animation: rainFall 0.62s linear infinite;
}
.wx-rain-far {
  background-image: repeating-linear-gradient(
    112deg,
    rgba(214, 234, 255, 0) 0 21px,
    rgba(214, 234, 255, 0.28) 21px 22px,
    rgba(214, 234, 255, 0) 22px 44px
  );
  background-size: 170px 420px;
  animation-name: rainFallFar;
  animation-duration: 1.05s;
}
/* One whole tile per cycle — anything else and the sheet visibly
   jumps back every loop. The travel matches the slant of the
   streaks: 110 across to 300 down is the same 20 degrees. */
@keyframes rainFall {
  to { background-position: -110px 300px; }
}
@keyframes rainFallFar {
  to { background-position: -170px 420px; }
}
.storm-2 .wx-rain { opacity: 0.55; }
.storm-3 .wx-rain { opacity: 1; animation-duration: 0.34s; }
.storm-3 .wx-rain-far { animation-duration: 0.6s; }

/* ---------- lightning ----------
   Fired from JS so the crack of thunder lands with the light.
   Two soft flickers, never more than a couple of frames bright,
   and nothing repeats faster than once every five seconds — well
   under the three-per-second threshold that can trigger seizures. */
.wx-bolt {
  inset: 0;
  background: #EAF2FF;
  opacity: 0;
}
.wx-bolt.striking { animation: boltFlash 0.85s ease-out; }
@keyframes boltFlash {
  0% { opacity: 0; }
  6% { opacity: 0.5; }
  14% { opacity: 0.06; }
  22% { opacity: 0.38; }
  40%, 100% { opacity: 0; }
}

/* ---------- the boss's own smoke ----------
   Tinted from the creature that threw it, so the oni's is embers
   and Whisper's is violet murk. --smoke is set per boss in JS. */
.boss-smoke {
  bottom: 6%;
  width: clamp(38px, 11vw, 76px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 55%, var(--smoke, #7a7a7a) 0%, rgba(0, 0, 0, 0) 70%);
  opacity: 0;
  pointer-events: none;
  z-index: 5;
  animation: bossSmoke 1.25s ease-out forwards;
}
@keyframes bossSmoke {
  0% { transform: translate(-50%, 26%) scale(0.3); opacity: 0; }
  22% { opacity: 0.9; }
  100% { transform: translate(-50%, -130%) scale(2); opacity: 0; }
}

/* ---------- the boss breathes ----------
   The player's monk has breathed since the SVG days. The boss
   sprites arrived later and stood perfectly still, which reads as a
   cardboard cut-out propped up opposite a living opponent.
   Anchored at the feet, so the ground line never moves. */
.fighter.boss .sprite-img,
.fighter.boss .char-svg {
  transform-origin: 50% 100%;
  animation: bossBreathe 3.4s ease-in-out infinite;
}
@keyframes bossBreathe {
  0%, 100% { transform: translateY(0) scale(1, 1); }
  50%      { transform: translateY(-0.6%) scale(1.012, 1.02); }
}
/* Whisper has no feet to plant — it hovers, so it drifts instead
   of swelling, and leans as it goes. */
.fighter.boss.boss-shadow .sprite-img {
  transform-origin: 50% 50%;
  animation: bossFloat 4.2s ease-in-out infinite;
}
@keyframes bossFloat {
  0%, 100% { transform: translateY(0) rotate(-1.5deg); }
  50%      { transform: translateY(-5%) rotate(1.5deg); }
}
/* Boulder is stone. It settles rather than breathes. */
.fighter.boss.boss-golem .sprite-img { animation-duration: 5.2s; }
/* A felled boss lies still. */
.boss-down .sprite-img,
.boss-down .char-svg { animation: none !important; }

/* ---------- a chain of right answers lifts the light ----------
   The mirror of the storm, kept much quieter: the transformation
   cut-ins already carry the drama of a long chain, and two big
   effects fighting each other read as one loud mess. */
.wx-shine {
  inset: 0;
  background: radial-gradient(120% 90% at 30% 105%, rgba(255, 214, 130, 0.85) 0%, rgba(255, 214, 130, 0) 62%);
  opacity: 0;
  transition: opacity 1.1s ease;
}
.sun-1 .wx-shine { opacity: 0.3; }
.sun-2 .wx-shine { opacity: 0.5; }
.sun-2 .wx-mote { display: block; }
.wx-mote {
  display: none;
  bottom: -12%;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #FFD98A;
  box-shadow: 0 0 8px 2px rgba(255, 217, 138, 0.75);
  animation: moteRise 4.4s linear infinite;
}
@keyframes moteRise {
  0% { transform: translateY(0) scale(0.6); opacity: 0; }
  12% { opacity: 0.9; }
  85% { opacity: 0.5; }
  100% { transform: translateY(-320px) scale(1.1); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .wx-rain,
  .wx-mote,
  .fighter.boss .sprite-img,
  .fighter.boss .char-svg,
  .fighter.boss.boss-shadow .sprite-img { animation: none !important; }
  .wx-bolt.striking { animation: none !important; }
  /* The weather still CHANGES — it just stops moving. Darkness and
     a still veil of rain say the same thing without the motion. */
  .storm-2 .wx-rain, .storm-3 .wx-rain { opacity: 0.4; }
}

/* The wind-up before a boss special: it swells and leans in, which
   gives the child a beat to brace before the blow lands. */
.boss-charge .sprite-holder { animation: bossCharge 0.44s ease-in-out; }
@keyframes bossCharge {
  0%, 100% { transform: scale(1) translateX(0) rotate(0); }
  55%      { transform: scale(1.13) translateX(7px) rotate(2.5deg); }
}
@media (prefers-reduced-motion: reduce) {
  .boss-charge .sprite-holder { animation: none !important; }
}

/* ============================================================
   TIME FREEZE — the world holds its breath for a special
   ------------------------------------------------------------
   From the moment a named form is called until the monk turns
   back, the whole screen takes on that form's colour and the
   ambient motion stops. It is the oldest trick in the genre and
   it works for the same reason it always did: everything else
   going still is what makes the strike look fast.

   Tier 1 is left alone on purpose. It fires on EVERY correct
   answer, and a screen that flashes on every right answer stops
   meaning anything by the third question.
   ============================================================ */

#time-freeze {
  position: fixed;
  inset: 0;
  z-index: 55;              /* under the cut-in at 60, over everything else */
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s ease;
  /* the tier colour, plus a vignette that pulls the eye to the middle */
  background:
    radial-gradient(115% 78% at 50% 46%, rgba(0, 0, 0, 0) 34%, rgba(0, 0, 0, 0.5) 100%),
    var(--freeze, #F2C14E);
}
#time-freeze.on { opacity: var(--freeze-a, 0.38); }

/* Nothing that was merely idling keeps idling. The fight itself
   carries on — the shakes, the sparks and the flurry are the
   whole point of the moment and are left running. */
body.time-frozen .wx-rain,
body.time-frozen .wx-mote,
body.time-frozen .fighter.boss .sprite-img,
body.time-frozen .fighter.boss .char-svg { animation-play-state: paused; }

@media (prefers-reduced-motion: reduce) {
  /* The colour still arrives, it just arrives at once. */
  #time-freeze { transition: none; }
}
