:root {
  --paper: #f3eddf;
  --paper-deep: #e7ddca;
  --ink: #173b36;
  --ink-soft: #4b625d;
  --red: #df553f;
  --red-dark: #be3e2d;
  --on-red: #fff;
  --jade: #b8d1bd;
  --white: #fffdf7;
  --line: rgba(23, 59, 54, 0.14);
  --shadow: 0 26px 60px rgba(37, 45, 34, 0.16), 0 5px 14px rgba(37, 45, 34, 0.08);
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { margin: 0; width: 100%; height: 100%; overflow: hidden; overscroll-behavior: none; }
body {
  height: 100dvh;
  background: #cfc9bd;
  color: var(--ink);
  font-family: "Manrope", system-ui, sans-serif;
}
button { font: inherit; color: inherit; touch-action: manipulation; }
button, img { -webkit-user-drag: none; }
button { user-select: none; }

.app-shell {
  position: relative;
  width: min(100%, 460px);
  height: 100dvh;
  min-height: 0;
  margin: 0 auto;
  overflow: hidden;
  background:
    radial-gradient(circle at 86% 4%, rgba(223, 85, 63, .11), transparent 30%),
    linear-gradient(155deg, #f8f3e9 0%, var(--paper) 65%, #eee5d5 100%);
}

[hidden] { display: none !important; }
.menu-screen {
  height: 100dvh;
  overflow-y: auto;
  padding: max(18px, env(safe-area-inset-top)) 20px max(28px, env(safe-area-inset-bottom));
  overscroll-behavior: contain;
}
.menu-header, .menu-player, .random-panel__top, .all-cards-panel__top, .section-heading, .all-cards-button, .all-cards-count {
  display: flex;
  align-items: center;
}
.menu-header { justify-content: space-between; }
.brand-mark {
  display: grid;
  width: 45px;
  height: 45px;
  place-items: center;
  border-radius: 50% 50% 50% 18%;
  background: var(--red);
  color: var(--on-red);
  font-family: "Noto Serif SC", serif;
  font-size: 24px;
  font-weight: 700;
  transform: rotate(-4deg);
}
.menu-player { gap: 7px; font-size: 12px; font-weight: 800; }
.menu-player .avatar { border-color: rgba(255,255,255,.65); }
.menu-intro { margin: clamp(28px, 6dvh, 54px) 2px 24px; }
.menu-intro h1 { max-width: 340px; font-size: clamp(36px, 10vw, 48px); line-height: 1.02; }
.menu-intro > p:last-child { max-width: 330px; margin: 13px 0 0; color: var(--ink-soft); font-size: 14px; line-height: 1.55; }
.random-panel {
  position: relative;
  overflow: hidden;
  padding: 20px;
  border-radius: 26px 26px 52px 26px;
  background: var(--ink);
  color: white;
  box-shadow: 0 18px 44px rgba(23,59,54,.16);
}
.random-panel::after {
  content: "";
  position: absolute;
  right: -42px;
  bottom: -65px;
  width: 150px;
  height: 150px;
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 50%;
  box-shadow: 0 0 0 28px rgba(255,255,255,.025), 0 0 0 56px rgba(255,255,255,.018);
}
.random-panel__top { position: relative; z-index: 1; justify-content: space-between; }
.menu-kicker { color: #e7a89b; font-size: 9px; font-weight: 800; letter-spacing: .15em; }
.random-panel h2 { margin-top: 3px; color: white; font-size: 24px; }
.random-glyph { font-family: "Noto Serif SC", serif; font-size: 50px; line-height: 1; opacity: .2; }
.deck-size { position: relative; z-index: 1; display: flex; gap: 8px; margin: 20px 0 12px; }
.deck-size button {
  min-width: 58px;
  min-height: 44px;
  border: 1px solid rgba(255,255,255,.18);
  border-radius: 13px;
  background: rgba(255,255,255,.07);
  color: white;
  font-size: 14px;
  font-weight: 800;
  cursor: pointer;
}
.deck-size button.is-selected { border-color: #f2b0a2; background: var(--red); }
.menu-primary {
  position: relative;
  z-index: 1;
  display: flex;
  width: 100%;
  min-height: 52px;
  align-items: center;
  justify-content: space-between;
  padding: 0 17px;
  border: 0;
  border-radius: 15px;
  background: var(--white);
  color: var(--ink);
  font-size: 14px;
  font-weight: 800;
  cursor: pointer;
}
.menu-primary span { font-size: 20px; }
#startReview { justify-content: center; text-align: center; }
/* A paused round: "continue" leads, a quiet reset sits to its right. */
.start-row { display: flex; gap: 8px; }
.start-row #startReview { flex: 1; }
.start-reset { flex: none; width: 52px; border: 1px solid rgba(255,255,255,.34); border-radius: 15px; background: rgba(255,255,255,.08); color: rgba(255,255,255,.8); font-size: 20px; font-weight: 700; cursor: pointer; }
.start-reset:hover { background: rgba(255,255,255,.16); color: white; }
.topics-section { margin-top: 28px; }
.section-heading { justify-content: space-between; margin: 0 2px 13px; }
.section-heading h2 { font-size: 21px; }
.section-heading span { color: var(--ink-soft); font-size: 11px; font-weight: 700; }
.topic-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 9px; }
.topic-button {
  min-width: 0;
  min-height: 118px;
  padding: 12px 9px;
  border: 1px solid var(--line);
  border-radius: 20px;
  background: rgba(var(--glass-rgb), .67);
  text-align: left;
  cursor: pointer;
}
.topic-glyph {
  display: grid;
  width: 42px;
  height: 42px;
  margin-bottom: 10px;
  place-items: center;
  border-radius: 50% 50% 16px 50%;
  font-family: "Noto Serif SC", serif;
  font-size: 22px;
  font-weight: 700;
}
.topic-glyph--coral { background: #f2c7bb; color: #9f3e2f; }
.topic-glyph--gold { background: #efdbac; color: #805b17; }
.topic-glyph--green { background: #c9ddca; color: #2f6659; }
.topic-glyph--blue { background: #c5dbe1; color: #326576; }
.topic-glyph--violet { background: #dad0e2; color: #634f75; }
.topic-glyph--ink { background: #cbd3cc; color: #294c46; }
.topic-glyph--rose { background: #e6c6cf; color: #8f4a5e; }
.topic-glyph--clay { background: #ddc9ac; color: #7a5230; }
.topic-button strong, .topic-button small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.topic-button strong { font-size: 12px; }
.topic-button small { margin-top: 3px; color: var(--ink-soft); font-size: 10px; }
.all-cards-panel {
  position: relative;
  overflow: hidden;
  margin-top: 14px;
  padding: 20px;
  border-radius: 26px 26px 52px 26px;
  background: #1b4650;
  color: white;
  box-shadow: 0 18px 44px rgba(23,59,54,.16);
}
.all-cards-panel::after {
  content: "";
  position: absolute;
  right: -42px;
  bottom: -65px;
  width: 150px;
  height: 150px;
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 50%;
  box-shadow: 0 0 0 28px rgba(255,255,255,.025), 0 0 0 56px rgba(255,255,255,.018);
}
.all-cards-panel__top { position: relative; z-index: 1; justify-content: space-between; }
.all-cards-panel .menu-kicker { color: #9cc9bb; }
.all-cards-panel h2 { margin-top: 3px; color: white; font-size: 24px; }
.panel-glyph { font-family: "Noto Serif SC", serif; font-size: 50px; line-height: 1; opacity: .2; }
.all-cards-button {
  position: relative;
  z-index: 1;
  width: 100%;
  min-height: 70px;
  justify-content: space-between;
  margin-top: 16px;
  padding: 0 17px;
  border: 1px solid rgba(255,255,255,.18);
  border-radius: 18px;
  background: rgba(255,255,255,.07);
  color: white;
  text-align: left;
  cursor: pointer;
}
.all-cards-copy strong, .all-cards-copy small { display: block; }
.all-cards-copy strong { font-size: 15px; }
.all-cards-copy small { margin-top: 3px; color: rgba(255,255,255,.68); font-size: 11px; }
.all-cards-total { opacity: .72; }
.all-cards-count { gap: 12px; }
.all-cards-count > span { display: grid; width: 36px; height: 36px; place-items: center; border-radius: 50%; background: var(--jade); color: var(--ink); font-size: 18px; }
.all-cards-panel .toggle-row { position: relative; z-index: 1; border-bottom: 0; }
.all-cards-panel .switch { background: rgba(255,255,255,.24); }
.all-cards-panel .toggle-row[aria-checked="true"] .switch { background: var(--jade); }

.toggle-row {
  display: flex;
  width: 100%;
  min-height: 46px;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 2px;
  border: 0;
  border-bottom: 1px solid var(--line);
  background: none;
  font-size: 13px;
  font-weight: 700;
  text-align: left;
  cursor: pointer;
}
.toggle-row:last-of-type { border-bottom: 0; }
.switch { position: relative; flex: 0 0 auto; width: 46px; height: 28px; border-radius: 999px; background: rgba(23,59,54,.22); transition: background .2s ease; }
.switch::after { content: ""; position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.25); transition: transform .2s ease; }
.toggle-row[aria-checked="true"] .switch { background: var(--red); }
.toggle-row[aria-checked="true"] .switch::after { transform: translateX(18px); }
.toggle-arrow { color: var(--red-dark); font-size: 18px; font-weight: 800; }

.game-screen {
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: max(16px, env(safe-area-inset-top)) 20px max(14px, env(safe-area-inset-bottom));
}

.topbar, .progress-row, .answer-buttons, .score-strip, .sheet-header {
  display: flex;
  align-items: center;
}
.topbar { justify-content: space-between; min-height: 44px; }
.topbar__left { display: flex; align-items: center; gap: 5px; }
.back-button { font-size: 25px; }
.avatar {
  display: inline-grid;
  width: 28px;
  height: 28px;
  place-items: center;
  border: 2px solid var(--paper);
  border-radius: 50%;
  color: white;
  font-size: 10px;
  font-weight: 800;
}
.avatar--red { background: var(--red); }
.avatar--blue { background: #467d8b; }
.avatar--gold { background: #c5953d; }
.icon-button, .close-button {
  display: grid;
  width: 44px;
  height: 44px;
  padding: 0;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
}
.icon-button svg { width: 23px; height: 23px; }

.eyebrow { margin: 0 0 4px; color: var(--red-dark); font-size: 11px; font-weight: 800; letter-spacing: .14em; }
h1, h2 { margin: 0; letter-spacing: -.04em; }
h1 { font-size: clamp(26px, 7vw, 32px); line-height: 1.1; }
h2 { font-size: 25px; }
.timer { position: relative; display: grid; width: 52px; height: 52px; place-items: center; }
.timer svg { position: absolute; inset: 0; width: 100%; height: 100%; transform: rotate(-90deg); }
.timer circle { fill: none; stroke-width: 3; }
.timer__track { stroke: rgba(23,59,54,.12); }
.timer__progress { stroke: var(--red); stroke-linecap: round; stroke-dasharray: 113.1; stroke-dashoffset: 0; transition: stroke-dashoffset .3s linear; }
.timer span { font-size: 11px; font-weight: 800; font-variant-numeric: tabular-nums; }
.timer.is-hidden { display: none; }

.progress-row { gap: 10px; margin: 14px 2px 14px; }
.progress-bar { flex: 1; height: 4px; overflow: hidden; border-radius: 99px; background: rgba(23,59,54,.11); }
.progress-bar span { display: block; width: 100%; height: 100%; border-radius: inherit; background: var(--red); transition: transform .35s ease-out; transform-origin: left; }
.progress-row > span { min-width: 40px; color: var(--ink-soft); font-size: 11px; font-weight: 800; }
.progress-row .timer { flex: 0 0 auto; width: 38px; height: 38px; }
.progress-row .timer span { font-size: 9px; }

.card-stage { position: relative; flex: 1; min-height: 0; perspective: 1300px; }
.card-swipe-surface {
  position: absolute;
  z-index: 1;
  inset: 0;
  perspective: 1300px;
  transition: transform .35s cubic-bezier(.2,.75,.25,1), opacity .35s ease;
  will-change: transform;
}
.card-swipe-surface.is-dragging { transition: none; }
.card-swipe-surface.is-reset { transition: none !important; }
.card-bookmark {
  position: absolute;
  z-index: 5;
  top: -7px;
  right: 24px;
  width: 38px;
  height: 58px;
  padding: 0;
  border: 2px solid #326576;
  border-top: 0;
  background: #d9e8ec;
  clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 76%, 0 100%);
  cursor: pointer;
  filter: drop-shadow(0 5px 5px rgba(37,45,34,.12));
}
.card-bookmark.is-active { background: #326576; }
.card-speak, .quiz-speak { display: inline-grid; place-items: center; width: 46px; height: 46px; border: 0; border-radius: 50%; background: linear-gradient(135deg, #fa8466, #cf4934); color: white; box-shadow: 0 4px 12px rgba(223,85,63,.3); cursor: pointer; }
.card-speak:active, .quiz-speak:active { transform: scale(.94); }
.card-speak { position: absolute; z-index: 5; top: 14px; left: 16px; }
.card-stack { position: absolute; z-index: 0; inset: 0; pointer-events: none; }
.stack-card {
  position: absolute;
  inset: 0;
  display: block;
  border: 1px solid rgba(255,255,255,.78);
  border-radius: 30px 30px 68px 30px;
  background: rgba(var(--glass-rgb), .72);
  box-shadow: 0 14px 36px rgba(37,45,34,.08);
  transform-origin: 50% 85%;
  transition: opacity .28s ease, transform .4s cubic-bezier(.2,.75,.25,1);
  backdrop-filter: blur(7px);
  -webkit-backdrop-filter: blur(7px);
}
.stack-card--3 { opacity: .38; transform: translate(4px, -17px) rotate(2.6deg) scale(.962); }
.stack-card--2 { opacity: .56; transform: translate(-5px, -11px) rotate(-1.8deg) scale(.976); }
.stack-card--1 { opacity: .82; transform: translate(3px, -5px) rotate(.8deg) scale(.99); }
.stack-card.is-hidden { opacity: 0; transform: translateY(0) scale(.94); }
.flashcard { position: absolute; z-index: 1; inset: 0; width: 100%; height: auto; min-height: 0; padding: 0; border: 0; background: none; cursor: pointer; touch-action: none; }
.flashcard.is-reset,
.flashcard.is-reset .flashcard__inner,
.flashcard.is-reset .flashcard__face,
.flashcard.no-flip .flashcard__inner,
.flashcard.no-flip .flashcard__face { transition: none !important; }
.swipe-cue {
  position: absolute;
  z-index: 3;
  top: 72px;
  display: flex;
  gap: 6px;
  align-items: center;
  padding: 9px 14px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: .02em;
  opacity: 0;
  pointer-events: none;
  transition: opacity .12s linear;
}
.swipe-cue span { font-size: 18px; }
.swipe-cue--miss { left: 18px; background: rgba(229,222,209,.94); color: #6f5d56; border: 2px solid #c8bda9; transform: rotate(-6deg); }
.swipe-cue--hit { right: 18px; background: rgba(23,59,54,.94); color: white; border: 2px solid #2f7061; transform: rotate(6deg); }
.swipe-hint { position: absolute; z-index: 4; inset: 0; display: flex; align-items: center; justify-content: space-between; padding: 0 10px; opacity: 0; transition: opacity .25s ease; pointer-events: none; }
.swipe-hint.is-visible { opacity: 1; }
.swipe-hint__side { display: flex; flex-direction: column; align-items: center; gap: 4px; max-width: 96px; color: var(--ink); }
/* Arrows sit on the card art, which is light in both themes; labels sit on the card. */
.swipe-hint__side--miss { color: var(--ink-soft); }
.swipe-hint__side--hit { color: var(--ink); }
.swipe-hint__side--miss .swipe-hint__arrow { color: #7a655c; }
.swipe-hint__side--hit .swipe-hint__arrow { color: #173b36; }
.swipe-hint__arrow { font-size: 46px; font-weight: 800; line-height: 1; }
.swipe-hint__label { font-size: 12px; font-weight: 800; text-align: center; }
.flashcard__inner { position: relative; display: block; width: 100%; height: 100%; transform-style: preserve-3d; -webkit-transform-style: preserve-3d; transition: transform .62s cubic-bezier(.2,.75,.25,1); }
.flashcard.is-flipped .flashcard__inner { transform: rotateY(180deg); }
.flashcard__face {
  position: absolute;
  inset: 0;
  display: flex;
  overflow: hidden;
  border-radius: 30px 30px 68px 30px;
  background: var(--white);
  box-shadow: var(--shadow);
  /* The visible face is decided purely by its orientation: no delayed
     visibility swap that can desync from the rotation and flash the other side. */
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
.flashcard__front { flex-direction: column; align-items: center; justify-content: center; padding: 28px; transform: rotateY(0deg) translateZ(1px); }
.flashcard__front::before {
  content: "";
  position: absolute;
  width: 180px;
  height: 180px;
  border: 1px solid rgba(223,85,63,.13);
  border-radius: 50%;
  box-shadow: 0 0 0 38px rgba(223,85,63,.04), 0 0 0 76px rgba(223,85,63,.025);
}
.card-label { z-index: 1; color: var(--red-dark); font-size: 10px; font-weight: 800; letter-spacing: .16em; }
.hanzi { z-index: 1; display: flex; align-items: center; justify-content: center; margin: -4px 0 6px; font-family: "Noto Serif SC", serif; font-size: clamp(64px, min(34vw, 24dvh), 160px); font-weight: 600; line-height: 1; }
.hanzi[data-length="2"] { font-size: clamp(52px, min(26vw, 18dvh), 120px); }
.hanzi[data-length="3"] { font-size: clamp(40px, min(20vw, 14dvh), 92px); }
.hanzi-char { color: var(--radical-color, var(--ink)); }
.pinyin { z-index: 1; font-size: 26px; font-weight: 600; }
.flip-hint {
  position: absolute;
  bottom: 24px;
  z-index: 2;
  padding: 9px 14px;
  border-radius: 999px;
  background: var(--ink);
  color: var(--white);
  font-size: 12px;
  font-weight: 800;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .24s ease, transform .24s ease;
}
.flip-hint.is-tutorial-visible { opacity: 1; transform: none; }
.flashcard__back { flex-direction: column; transform: rotateY(180deg) translateZ(1px); }
.association { display: block; width: 100%; height: 54%; flex: 0 0 54%; min-height: 0; object-fit: contain; object-position: center; background: var(--muted); transition: opacity .12s ease; }
.association.is-loading,
.quiz-image.is-loading { opacity: 0; }
.back-copy { display: flex; flex: 1 1 auto; min-height: 0; flex-direction: column; align-items: center; justify-content: center; padding: 14px 18px; overflow: hidden; }
.translation { margin: 4px 0 2px; max-width: 100%; font-size: clamp(20px, 5.6vw, 32px); font-weight: 800; letter-spacing: -.03em; line-height: 1.12; text-align: center; overflow-wrap: anywhere; }
.back-pinyin { color: var(--ink-soft); font-size: 15px; font-weight: 600; text-align: center; }
.back-hanzi { font-family: "Noto Serif SC", serif; font-weight: 700; }

.answer-area { height: 93px; padding-top: 13px; opacity: 0; pointer-events: none; transform: translateY(8px); transition: opacity .2s ease, transform .2s ease; }
.answer-area.is-visible { opacity: 1; pointer-events: auto; transform: none; }
.answer-area p { margin: 0 0 8px; color: var(--ink-soft); text-align: center; font-size: 11px; font-weight: 700; }
.answer-buttons { gap: 10px; }
.answer-button { flex: 1; min-height: 48px; border: 0; border-radius: 16px; font-size: 14px; font-weight: 800; cursor: pointer; }
.answer-button span { margin-right: 4px; font-size: 20px; vertical-align: -1px; }
.answer-button--miss { background: var(--white); color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); }
.answer-button--miss span:first-child { color: var(--red); }
.answer-button--hit { background: var(--ink); color: var(--on-ink); }

.score-strip { justify-content: center; gap: 16px; margin-top: 10px; padding-top: 12px; border-top: 1px solid var(--line); }
.score-player { display: grid; grid-template-columns: 28px auto auto; column-gap: 8px; align-items: center; }
.score-player .avatar { grid-row: 1; }
.score-player span:not(.avatar) { font-size: 12px; font-weight: 700; }
.score-player strong { font-size: 18px; line-height: 1; }

.result-screen {
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: max(22px, env(safe-area-inset-top)) 20px max(20px, env(safe-area-inset-bottom));
}
.result-heading h1 { font-size: clamp(30px, 8vw, 38px); }
.result-summary { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin: 20px 0 16px; }
.result-stat { padding: 15px 17px; border: 1px solid var(--line); border-radius: 20px; background: rgba(var(--glass-rgb), .72); }
.result-stat b { display: block; font-size: 34px; line-height: 1; letter-spacing: -.04em; }
.result-stat span { display: block; margin-top: 5px; color: var(--ink-soft); font-size: 10px; font-weight: 800; letter-spacing: .1em; }
.result-stat--hit b { color: var(--hit); }
.result-stat--miss b { color: var(--red-dark); }
/* The bar behind the row fills to the level progress, like the home level chip. */
.result-xp { position: relative; isolation: isolate; display: flex; align-items: baseline; justify-content: space-between; gap: 10px; overflow: hidden; margin: 0 0 16px; padding: 10px 16px; border: 1px solid var(--line); border-radius: 999px; background: rgba(var(--glass-rgb), .66); }
.result-xp::before { content: ""; position: absolute; inset: 0; z-index: -1; background: linear-gradient(90deg, rgba(239,184,142,.45), rgba(223,85,63,.28)); transform-origin: left; transform: scaleX(var(--xp, 0)); transition: transform .5s cubic-bezier(.2,.75,.25,1); }
.result-xp b { color: var(--red-dark); font-size: 17px; font-weight: 800; letter-spacing: -.01em; }
.result-xp span { color: var(--ink-soft); font-size: 12px; font-weight: 700; text-align: right; }
.result-list { flex: 1; min-height: 0; margin: 0; padding: 0; list-style: none; overflow-y: auto; overscroll-behavior: contain; border-top: 1px solid var(--line); }
.result-item { border-bottom: 1px solid var(--line); font-size: 14px; }
.result-item__open { display: flex; width: 100%; gap: 10px; padding: 12px 4px; border: 0; background: transparent; color: var(--ink); text-align: left; cursor: pointer; }
.result-item__open:hover { background: rgba(23,59,54,.04); }
.result-mark { flex: 0 0 auto; width: 18px; font-weight: 800; text-align: center; }
.result-item.is-hit .result-mark { color: var(--hit); }
.result-item.is-miss .result-mark { color: var(--red); }
.result-word { min-width: 0; overflow-wrap: anywhere; }
.result-hanzi { color: var(--ink); font-family: "Noto Serif SC", serif; font-weight: 700; }
.result-item__open:hover .result-hanzi, .result-item__open:focus-visible .result-hanzi { color: var(--red-dark); }
.result-pinyin { margin-left: 4px; color: var(--ink-soft); }
.result-translation { color: var(--ink-soft); }
.result-home { display: flex; width: 100%; min-height: 56px; align-items: center; justify-content: center; gap: 10px; margin-top: 16px; border: 0; border-radius: 18px; background: var(--ink); color: var(--on-ink); font-size: 15px; font-weight: 800; cursor: pointer; }
.result-home span { font-size: 20px; }

.sheet-backdrop { position: absolute; z-index: 5; inset: 0; background: rgba(20,33,30,.33); backdrop-filter: blur(3px); }
.settings-sheet {
  position: absolute;
  z-index: 6;
  right: 0;
  bottom: 0;
  left: 0;
  max-height: calc(100% - 16px);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: 10px 20px max(18px, env(safe-area-inset-bottom));
  border-radius: 30px 30px 0 0;
  background: var(--white);
  box-shadow: 0 -20px 60px rgba(20,33,30,.18);
  transform: translateY(105%);
  transition: transform .38s cubic-bezier(.2,.8,.2,1);
}
.settings-sheet.is-open { transform: none; }
.sheet-handle { width: 38px; height: 4px; margin: 0 auto 17px; border-radius: 99px; background: #d5cdbf; }
.sheet-header { justify-content: space-between; margin-bottom: 22px; }
.close-button { background: var(--muted); font-size: 28px; font-weight: 400; }
fieldset { margin: 0 0 20px; padding: 0; border: 0; }
legend { margin-bottom: 10px; font-size: 13px; font-weight: 800; }
.segmented { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }
.segmented button { min-height: 92px; padding: 12px; border: 1px solid var(--line); border-radius: 18px; background: var(--surface); cursor: pointer; }
.segmented button strong { display: block; font-family: "Noto Serif SC", serif; font-size: 28px; }
.segmented button span { display: block; margin-top: 2px; font-size: 11px; font-weight: 700; }
.segmented button.is-selected { border-color: var(--red); background: var(--tint-red); box-shadow: inset 0 0 0 1px var(--red); }
.segmented--sm { grid-template-columns: 1fr 1fr; }
.segmented--sm button { min-height: 58px; }
.segmented--sm button strong { font-size: 22px; }
.timer-options { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.timer-options button { min-height: 44px; border: 1px solid var(--line); border-radius: 14px; background: transparent; font-size: 12px; font-weight: 700; cursor: pointer; }
.timer-options button.is-selected { border-color: var(--ink); background: var(--ink); color: var(--on-ink); }
.start-button { display: flex; width: 100%; min-height: 56px; align-items: center; justify-content: center; padding: 0 20px; border: 0; border-radius: 18px; background: var(--red); color: var(--on-red); font-weight: 800; cursor: pointer; }
.start-button span { font-size: 15px; }
.toast { position: absolute; z-index: 9; bottom: 24px; left: 50%; padding: 10px 14px; border-radius: 12px; background: var(--ink); color: var(--on-ink); font-size: 12px; font-weight: 700; opacity: 0; transform: translate(-50%, 10px); transition: .2s ease; pointer-events: none; }
.toast.is-visible { opacity: 1; transform: translate(-50%, 0); }

button:focus-visible { outline: 3px solid rgba(223,85,63,.38); outline-offset: 3px; }
button:active { transform: scale(.97); transition: transform .08s ease; }
.flashcard:active { transform: none; }

@media (max-height: 740px) {
  .menu-intro { margin-block: 20px 18px; }
  .topic-button { min-height: 105px; }
  .progress-row { margin-block: 10px; }
  .score-strip { margin-top: 4px; }
  /* Too short for a list inside the page: the whole results screen scrolls. */
  .result-screen { overflow-y: auto; }
  .result-list { flex: 0 0 auto; overflow: visible; }
}
@media (min-width: 461px) {
  body { padding-block: 20px; }
  .app-shell { height: calc(100dvh - 40px); min-height: 0; border-radius: 36px; box-shadow: 0 30px 80px rgba(35,40,35,.25); }
  .game-screen, .result-screen, .menu-screen { height: 100%; }
  .settings-sheet { border-radius: 30px; bottom: 10px; left: 10px; right: 10px; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { scroll-behavior: auto !important; transition-duration: .01ms !important; animation-duration: .01ms !important; }
}
@media (hover: hover) and (pointer: fine) {
  .icon-button:hover, .close-button:hover { background: rgba(23,59,54,.08); }
  .answer-button--hit:hover { background: #24564e; }
  .answer-button--miss:hover { background: var(--tint-red); }
  .start-button:hover { background: var(--red-dark); }
  .menu-primary:hover { background: var(--red-dark); }
  /* Neutral, so a hovered option never looks like a wrong answer. */
  .probe-option:not(:disabled):hover { border-color: var(--ink-soft); }
}

/* ================================================================== *
 * Learning product — new screens & components
 * ================================================================== */

.view { height: 100%; min-height: 0; }
.home-screen,
.collection-screen,
.detail-screen,
.confuse-screen {
  display: flex;
  flex-direction: column;
  padding: max(16px, env(safe-area-inset-top)) 20px max(24px, env(safe-area-inset-bottom));
}
.home-screen { overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
.collection-screen, .detail-screen, .confuse-screen { height: 100%; }

.topbar__actions { display: flex; align-items: center; gap: 2px; }
.brand { display: flex; align-items: center; gap: 9px; }
.brand-name { font-weight: 800; font-size: 16px; letter-spacing: -.02em; }
.telegram-profile { display: flex; align-items: center; margin-right: 4px; }
.telegram-avatar,
.telegram-avatar-fallback { flex: 0 0 auto; width: 28px; height: 28px; border-radius: 50%; }
.telegram-avatar { display: block; object-fit: cover; }
.telegram-avatar-fallback { display: grid; place-items: center; background: var(--jade); color: var(--ink); font-size: 11px; font-weight: 800; }

/* --- home --- */
.home-hero { text-align: center; margin: 4px 0 10px; }
.mascot-slot { display: grid; place-items: center; }
/* The card in Bao's paw opens its character (app.js mascotInto); the hit area reaches past the small card. */
.mascot-slot:has(> .mascot-card) { position: relative; }
.mascot-card { position: absolute; padding: 0; border: 0; border-radius: 14%; background: transparent; cursor: pointer; rotate: 5.5deg; -webkit-tap-highlight-color: transparent; }
.mascot-card::before { content: ""; position: absolute; inset: -8px; }
.mascot-slot .mascot { transition: scale .12s ease-out; }
.mascot-slot:has(> .mascot-card:active) .mascot { scale: .95; }
.mascot-slot--hero { width: 100px; height: 100px; margin: 0 auto 2px; }
.mascot-slot--overlay { width: 118px; height: 118px; margin: 0 auto 6px; }
/*
 * Achievement stickers standing in for Bao (unlock modal, onboarding). They
 * move like Bao in the trailer: drop in, squash on landing, then breathe.
 * `translate`/`scale` animate while `rotate` keeps each sticker's tilt.
 */
.sticker-stack { position: relative; display: flex; justify-content: center; align-items: center; --sticker: 148px; }
.sticker-stack[data-count="2"] { --sticker: 118px; }
.sticker-stack[data-count="3"] { --sticker: 110px; }
.mascot-slot--overlay.sticker-stack { width: auto; height: 136px; }
/*
 * Animated stickers carry a drop shadow. While a transform animates, the
 * browser draws the sticker as its own layer clipped to its box, so a shadow
 * reaching past the box shows straight edges. --pad gives the shadow room
 * inside the box; the matching negative margin keeps the visible size.
 */
.sticker { --pad: 22px; position: relative; display: block; box-sizing: content-box; width: var(--sticker); height: 100%; margin: calc(var(--pad) * -1); padding: var(--pad); object-fit: contain; filter: drop-shadow(0 8px 12px rgba(37,45,34,.2)); transform-origin: 50% 90%; rotate: var(--tilt, 0deg); animation: sticker-land .7s var(--delay, 0s) both, sticker-breathe 2.8s ease-in-out calc(var(--delay, 0s) + .7s) infinite; }
.sticker + .sticker { margin-left: calc(var(--sticker) * -.16 - var(--pad)); }
.sticker > img, .achievement__art > img { display: block; width: 100%; height: 100%; object-fit: contain; }
.sticker:nth-of-type(1) { --tilt: -4deg; }
.sticker:nth-of-type(2) { --tilt: 3deg; --delay: .12s; }
.sticker:nth-of-type(3) { --tilt: -2deg; --delay: .24s; }
.sticker:only-of-type { --tilt: 0deg; }
.sticker-spark { position: absolute; left: var(--x); top: var(--y); width: var(--s, 14px); height: var(--s, 14px); background: #ffc93c; clip-path: polygon(50% 0, 61% 39%, 100% 50%, 61% 61%, 50% 100%, 39% 61%, 0 50%, 39% 39%); opacity: 0; animation: sticker-spark 2.4s var(--spark-delay, .5s) ease-in-out infinite; pointer-events: none; }
@keyframes sticker-land {
  0% { opacity: 0; translate: 0 -48px; scale: .72; }
  42% { opacity: 1; translate: 0 0; scale: .95 1.07; }
  60% { scale: 1.12 .86; }
  78% { scale: .96 1.05; }
  100% { translate: 0 0; scale: 1; }
}
@keyframes sticker-breathe { 0%, 100% { translate: 0 0; scale: 1; } 50% { translate: 0 -3px; scale: 1.014 .986; } }
@keyframes sticker-spark { 0%, 100% { opacity: 0; scale: .2; rotate: 0deg; } 30% { opacity: 1; scale: 1; } 60% { opacity: 0; scale: .4; rotate: 90deg; } }
/* A tap on an earned sticker makes it hop. */
@keyframes sticker-hop {
  0% { translate: 0 0; scale: 1; }
  15% { scale: 1.08 .9; }
  45% { translate: 0 -16px; scale: .95 1.06; }
  72% { translate: 0 0; scale: 1.1 .88; }
  86% { scale: .97 1.03; }
  100% { translate: 0 0; scale: 1; }
}
@media (prefers-reduced-motion: reduce) { .sticker, .sticker-spark { animation: none; } .sticker-spark { display: none; } }
.mascot { width: 100%; height: 100%; object-fit: contain; }
/* The face waits for the body image (mascot.js); after 1.2 s it shows anyway. */
.mascot .bao-face { opacity: 0; animation: bao-face-show 0s 1.2s forwards; }
.mascot.is-ready .bao-face { opacity: 1; animation: none; }
@keyframes bao-face-show { to { opacity: 1; } }
.mascot--idle { animation: mascot-bob 3.4s ease-in-out infinite; }
.mascot--celebrating { animation: mascot-pop .6s ease-out; }
.mascot--watering { animation: mascot-tilt 1.6s ease-in-out infinite; }
@keyframes mascot-bob { 0%,100% { transform: translateY(0) } 50% { transform: translateY(-3px) } }
@keyframes mascot-pop { 0% { transform: scale(.9) } 60% { transform: scale(1.06) } 100% { transform: scale(1) } }
@keyframes mascot-tilt { 0%,100% { transform: rotate(-3deg) } 50% { transform: rotate(3deg) } }
/* Bao's face (mascot.js): every Bao blinks on its own rhythm. */
.mascot .bao-eye { transform-box: fill-box; transform-origin: center; animation: bao-blink 4.4s var(--blink-delay, 0s) infinite; }
@keyframes bao-blink { 0%, 93%, 100% { transform: scaleY(1) } 95.5% { transform: scaleY(.08) } }

.streak-chip { display: inline-block; margin: 0 0 4px; padding: 4px 10px; border-radius: 999px; background: var(--tint-red); color: var(--red-dark); font-size: 11px; font-weight: 800; }
.home-next { color: var(--green-ink); font-weight: 700; }
.home-next:not(:empty)::before { content: " · "; color: var(--ink-soft); font-weight: 600; }

.progress-track { height: 8px; overflow: hidden; border-radius: 99px; background: rgba(23,59,54,.11); }
.progress-track > span { display: block; width: 100%; height: 100%; border-radius: inherit; background: var(--red); transform-origin: left; transform: scaleX(0); transition: transform .5s cubic-bezier(.2,.75,.25,1); }
.progress-track--lg { height: 9px; }

.today-card { position: relative; padding: 14px; margin-bottom: 8px; border-radius: 22px 22px 38px 22px; background: var(--strong); color: var(--on-strong); box-shadow: 0 16px 40px rgba(23,59,54,.16); }
.today-card .menu-kicker { color: #e7a89b; }
.today-card h2 { margin: 3px 0; color: white; font-size: 20px; }
.today-sub { margin: 0 0 10px; color: rgba(255,255,255,.72); font-size: 11px; font-weight: 600; }
.menu-primary { display: flex; width: 100%; min-height: 44px; align-items: center; justify-content: center; gap: 10px; padding: 0 18px; border: 0; border-radius: 15px; background: var(--red); color: var(--on-red); font-size: 14px; font-weight: 800; text-align: center; cursor: pointer; }
.menu-primary span { font-size: inherit; }
.menu-primary:disabled, .menu-primary:disabled:hover { background: var(--muted); color: var(--ink-soft); cursor: default; }
#tutorialNext { transition: background .2s ease, color .2s ease; }
.menu-secondary { display: flex; width: 100%; min-height: 42px; align-items: center; justify-content: center; gap: 8px; margin-top: 6px; border: 1px solid var(--line); border-radius: 14px; background: rgba(var(--glass-rgb), .6); color: var(--ink); font-size: 13px; font-weight: 800; text-align: center; cursor: pointer; }


.link-button { padding: 4px 2px; border: 0; background: none; color: var(--red-dark); font-size: 12px; font-weight: 800; cursor: pointer; }

/* --- session --- */
.session-progress { flex: 1; height: 5px; margin: 0 12px; overflow: hidden; border-radius: 99px; background: rgba(23,59,54,.11); }
.session-progress > span { display: block; width: 100%; height: 100%; border-radius: inherit; background: var(--red); transform-origin: left; transform: scaleX(0); transition: transform .35s ease-out; }
.session-counter { color: var(--ink-soft); font-size: 11px; font-weight: 800; font-variant-numeric: tabular-nums; }
.card-tag { position: absolute; top: 16px; left: 50%; z-index: 2; max-width: calc(100% - 144px); overflow: hidden; transform: translateX(-50%); padding: 4px 12px; border-radius: 999px; background: rgba(223,85,63,.12); color: var(--red-dark); font-size: 10px; font-weight: 800; letter-spacing: .06em; text-overflow: ellipsis; text-transform: uppercase; white-space: nowrap; }
.mnemonic { margin-top: 8px; color: var(--ink-soft); font-size: 12px; line-height: 1.4; text-align: center; }

.session-actions { display: flex; gap: 10px; height: 74px; align-items: center; }
.reveal-actions { display: flex; height: 74px; align-items: center; }
.reveal-continue { display: block; width: 100%; min-height: 52px; border: 0; border-radius: 16px; background: var(--ink); color: var(--on-ink); font-size: 15px; font-weight: 800; cursor: pointer; }

.probe { position: absolute; z-index: 5; inset: 0; display: flex; flex-direction: column; justify-content: center; gap: 12px; padding: 22px; border-radius: 30px 30px 68px 30px; background: var(--white); box-shadow: var(--shadow); }
.probe__title { margin: 0; color: var(--red-dark); font-size: 10px; font-weight: 800; letter-spacing: .16em; text-align: center; text-transform: uppercase; }
/* Taking over from a flashcard, the question panel eases in instead of popping. */
.probe.is-entering { animation: probe-enter .38s cubic-bezier(.2, .8, .2, 1) both; }
.probe.is-entering .probe__title { animation: probe-title .5s .12s cubic-bezier(.3, 1.5, .5, 1) both; }
@keyframes probe-enter { from { opacity: 0; transform: translateY(22px) scale(.97); } }
@keyframes probe-title { from { opacity: 0; transform: scale(.6); } }
@media (prefers-reduced-motion: reduce) { .probe.is-entering, .probe.is-entering .probe__title { animation: none; } }
.probe__question { margin: 0 0 6px; font-size: 20px; font-weight: 800; line-height: 1.2; text-align: center; }
.probe__options { display: grid; gap: 9px; }
.probe-option { min-height: 54px; padding: 10px 14px; border: 1px solid var(--line); border-radius: 15px; background: var(--surface); font-size: 16px; font-weight: 700; cursor: pointer; }

/* --- result extras --- */
.result-breakdown { margin: 0 0 14px; padding: 14px 16px; border-radius: 16px; background: rgba(var(--jade-rgb), .4); font-size: 13px; font-weight: 700; }
.result-breakdown p { margin: 2px 0; }

/* --- collection --- */
.collection-count { color: var(--ink-soft); font-size: 12px; font-weight: 800; font-variant-numeric: tabular-nums; }
.search-field { display: block; margin: 8px 0 10px; }
.search-field input { width: 100%; min-height: 46px; padding: 0 15px; border: 1px solid var(--line); border-radius: 14px; background: rgba(var(--glass-rgb), .8); color: var(--ink); font: inherit; font-size: 14px; }
.search-field input:focus { outline: 2px solid rgba(223,85,63,.35); }
.filter-row { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 12px; }
.chip { padding: 8px 13px; border: 1px solid var(--line); border-radius: 999px; background: rgba(var(--glass-rgb), .6); font-size: 12px; font-weight: 700; cursor: pointer; }
.chip.is-selected { border-color: var(--ink); background: var(--ink); color: var(--on-ink); }
.character-grid { display: grid; flex: 1; min-height: 0; grid-template-columns: repeat(auto-fill, minmax(66px, 1fr)); gap: 8px; align-content: start; overflow-y: auto; overscroll-behavior: contain; }
/* The grid runs down to the tab bar. Its padding keeps the due ring and
   borders of edge tiles inside the scroll box, and the edges fade instead
   of cutting tiles off. */
.collection-screen { padding-bottom: 0; }
.collection-screen .filter-row { margin-bottom: 0; }
.character-grid {
  margin: 0 -6px; padding: 12px 6px 20px;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 12px, #000 calc(100% - 16px), transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 12px, #000 calc(100% - 16px), transparent 100%);
}
.character-tile { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; aspect-ratio: 1 / 1; border: 1px solid var(--line); border-radius: 16px; background: rgba(var(--glass-rgb), .72); cursor: pointer; }
.character-tile__hanzi { font-family: "Noto Serif SC", serif; font-size: 27px; line-height: 1; }
.character-tile__meta { color: var(--ink-soft); font-size: 9px; font-weight: 700; }
.character-tile.state-new { opacity: .5; }
.character-tile.state-new .character-tile__hanzi { color: #8b8b82; }
.character-tile.state-familiar { border-color: #cfe0cf; background: rgba(var(--jade-rgb), .5); }
/* "Помню": a still jade sheen. "Освоил" gets the shine foil below. */
.character-tile.state-remembered { border-color: #b9d3bd; background: linear-gradient(135deg, rgba(var(--jade-rgb), .62), rgba(255,255,255,.4) 48%, rgba(var(--jade-rgb), .5)); }
.character-tile.shine .character-tile__meta { color: var(--shine-ink); opacity: .75; }
.character-tile.is-due { box-shadow: 0 0 0 2px rgba(223,85,63,.35); }
.character-tile__due { position: absolute; top: 5px; right: 5px; width: 8px; height: 8px; border-radius: 99px; background: var(--red); overflow: hidden; font-size: 0; }
/* Best writing on the card: traced (faint), from memory, from memory with no mistakes (gold). */
.character-tile__writing { position: absolute; top: 4px; left: 6px; color: var(--ink-soft); font-size: 10px; line-height: 1; opacity: .45; }
.character-tile__writing.is-level-2 { opacity: .9; }
.character-tile__writing.is-level-3 { color: #b8860b; opacity: 1; }
.empty-state { padding: 30px 10px; color: var(--ink-soft); font-size: 14px; text-align: center; }

/* --- detail --- */
.detail-hero { padding: 4px 0 10px; text-align: center; }
.detail-pronunciation { display: flex; align-items: center; justify-content: center; gap: 10px; margin-top: 6px; }
.detail-pronunciation__sep { color: var(--ink-soft); font-size: 19px; font-weight: 600; }
.detail-pronunciation:not(:has(.detail-speak:not([hidden]))) .detail-pronunciation__sep { display: none; }
.detail-speak { display: inline-grid; place-items: center; width: 34px; height: 34px; padding: 0; border: 0; border-radius: 99px; color: #fff; cursor: pointer; background: linear-gradient(135deg, rgba(255,122,89,.82), rgba(223,85,63,.82) 55%, rgba(199,62,44,.82)); box-shadow: 0 4px 12px rgba(223,85,63,.3), inset 0 1px 0 rgba(255,255,255,.3); }
.detail-speak:hover { box-shadow: 0 6px 16px rgba(223,85,63,.42), inset 0 1px 0 rgba(255,255,255,.3); transform: translateY(-1px); }
.detail-speak:active { transform: scale(.94); }
.detail-bookmark { min-height: 34px; padding: 0 12px; border: 1px solid var(--red); border-radius: 12px; background: transparent; color: var(--red-dark); font-size: 11px; font-weight: 800; cursor: pointer; }
.detail-bookmark.is-active { background: var(--red); color: var(--on-red); }
.detail-hanzi { display: block; margin: 0 auto; padding: 0; border: 0; background: none; font-family: "Noto Serif SC", serif; font-size: clamp(64px, 22vw, 100px); line-height: 1; font-weight: 600; cursor: pointer; }
.detail-pinyin { color: var(--ink-soft); font-size: 19px; font-weight: 600; }
.detail-translation { display: block; margin-top: 1px; font-size: 15px; font-weight: 700; }
.detail-rows { display: grid; gap: 1px; }
.detail-row { display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 4px 10px; padding: 8px 4px; border-bottom: 1px solid var(--line); font-size: 12px; }
.detail-row__label { color: var(--ink-soft); font-weight: 600; }
.detail-row__value { font-weight: 800; }
.detail-row__bar { grid-column: 1 / -1; height: 6px; overflow: hidden; border-radius: 99px; background: rgba(23,59,54,.11); }
.detail-row__bar > span { display: block; width: 100%; height: 100%; border-radius: inherit; background: var(--red); transform-origin: left; }
.detail-sections { margin-top: 10px; }
.composition-row { display: flex; align-items: flex-start; justify-content: center; flex-wrap: wrap; gap: 10px; padding: 4px 0 2px; }
.composition-cell { display: flex; flex-direction: column; align-items: center; gap: 2px; min-width: 58px; }
.composition-cell__glyph { font-family: "Noto Serif SC", serif; font-size: 44px; line-height: 1.15; font-weight: 600; }
.composition-cell__role { font-size: 9.5px; font-weight: 800; letter-spacing: .4px; text-transform: lowercase; color: var(--ink-soft); opacity: .85; }
.composition-cell__role--radical { color: var(--red-dark); opacity: 1; }
.composition-cell__role--phonetic { color: #3e6f91; opacity: 1; }
.composition-cell__role--semantic { color: #2f7061; opacity: 1; }
.composition-cell__gloss { color: var(--ink-soft); font-size: 11.5px; font-weight: 700; text-align: center; line-height: 1.3; }
.composition-plus { color: var(--ink-soft); font-size: 20px; font-weight: 600; padding: 12px 2px 0; }
.detail-section { margin-bottom: 8px; }
.detail-section h3 { margin: 0 0 3px; font-size: 12px; }
.detail-section p { margin: 0; color: var(--ink-soft); font-size: 12px; line-height: 1.4; }
.detail-examples { margin-top: 10px; }
.component-hanzi { cursor: default; }
.component-key { display: inline-block; margin-top: 8px; }
.component-card { display: block; margin: 10px auto 0; }
.component-usage { margin-top: 6px; }
.component-usage h3 { font-size: 14px; }
.component-grid { flex: none; overflow: visible; margin: 8px 0 0; padding: 4px 0 8px; -webkit-mask-image: none; mask-image: none; }
.detail-screen {
  overflow-y: auto;
}
.detail-example {
  padding: 12px;
  border-radius: 18px;
  background: var(--white);
  box-shadow: 0 10px 26px rgba(37, 45, 34, .08), 0 2px 6px rgba(37, 45, 34, .05);
}
.detail-example h3 { margin-bottom: 8px; color: var(--ink-soft); letter-spacing: .04em; text-transform: uppercase; }
.detail-example__list { display: grid; gap: 10px; }
.detail-example__item + .detail-example__item { padding-top: 10px; border-top: 1px solid var(--line); }
.detail-example__zh { margin: 0; font-family: "Noto Serif SC", serif; font-size: 19px; line-height: 1.4; color: var(--ink); }
.detail-example__target { color: var(--red); font-weight: 700; }
.detail-example__pinyin { display: block; margin-top: 4px; color: var(--ink-soft); font-size: 12px; letter-spacing: .01em; }
.detail-example__ru { display: block; margin-top: 3px; color: var(--ink-soft); font-size: 12px; line-height: 1.4; }
.detail-example__more { width: 100%; min-height: 34px; margin-top: 10px; border: 0; border-radius: 12px; background: var(--paper-deep); color: var(--ink); font-size: 12px; font-weight: 800; cursor: pointer; }
.detail-example__more::after { content: " ↓"; }
/* The card page's actions stay at the bottom while the page scrolls under
   them: the bar, not the page, carries the bottom inset (a sticky bar stops
   at its scroller's padding edge), and fades the page out above it. Short
   pages still push it to the bottom (margin-top: auto). */
.detail-screen:has(> .detail-actions) { padding-bottom: 0; }
.detail-actions {
  position: sticky;
  z-index: 2;
  bottom: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: auto -20px 0;
  padding: 24px 20px max(16px, env(safe-area-inset-bottom));
  background: linear-gradient(180deg, transparent, var(--paper) 24px);
}
.detail-write { border: 1.5px solid var(--ink); background: transparent; color: var(--ink); }

.examples-modal { position: absolute; z-index: 12; inset: 0; display: flex; align-items: flex-end; }
.examples-modal[hidden] { display: none; }
.examples-modal__backdrop { position: absolute; inset: 0; background: rgba(20,33,30,.42); backdrop-filter: blur(3px); }
.examples-modal__sheet {
  position: relative;
  display: flex;
  width: 100%;
  max-height: calc(100% - max(20px, env(safe-area-inset-top)));
  flex-direction: column;
  padding: 18px 20px max(24px, env(safe-area-inset-bottom));
  border-radius: 28px 28px 0 0;
  background: var(--white);
  box-shadow: 0 -20px 60px rgba(20,33,30,.22);
}
.examples-modal__header { display: flex; flex: 0 0 auto; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 14px; }
.examples-modal__header h2 { font-size: 21px; }
.examples-modal__list { min-height: 0; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; padding: 2px 2px 8px; }

/* --- confusions --- */
.confuse-list { display: grid; gap: 10px; overflow-y: auto; }
.confuse-row { padding: 14px; border: 1px solid var(--line); border-radius: 18px; background: rgba(var(--glass-rgb), .72); }
.confuse-chars { display: flex; align-items: center; justify-content: space-around; gap: 12px; }
.confuse-char { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.confuse-glyph { font-family: "Noto Serif SC", serif; font-size: 40px; line-height: 1; }
.confuse-char small { color: var(--ink-soft); font-size: 10px; font-weight: 700; text-align: center; }
.pro-teaser { margin-top: auto; padding: 16px; border-radius: 18px; background: rgba(223,85,63,.08); }
.pro-teaser p { margin: 0 0 12px; font-size: 13px; font-weight: 700; line-height: 1.45; }

/* --- overlays --- */
.overlay { position: absolute; z-index: 10; inset: 0; display: grid; place-items: center; padding: 24px; background: rgba(20,33,30,.42); backdrop-filter: blur(3px); }
.overlay-card { width: 100%; max-width: 360px; padding: 24px; border-radius: 26px; background: var(--white); box-shadow: 0 26px 60px rgba(20,33,30,.28); text-align: center; }
.overlay-card h2 { margin: 4px 0 8px; font-size: 24px; }
.overlay-lead { margin: 0 0 10px; color: var(--ink-soft); font-size: 14px; line-height: 1.5; }
.overlay-benefit { margin: 0 0 10px; font-size: 13px; font-weight: 700; line-height: 1.5; }
.overlay-note { margin: 12px 0 14px; color: #9a8f83; font-size: 11px; font-weight: 600; }
.overlay-card .menu-primary { justify-content: center; }
.overlay-card .link-button { display: block; margin: 10px auto 0; }

@media (prefers-reduced-motion: reduce) {
  .mascot--idle, .mascot--celebrating, .mascot--watering { animation: none !important; }
  .mascot .bao-eye, .result-bao__mascot .mascot, .result-bao__line { animation: none !important; }
}

/* layout fixes for inner headers + overlays */
.confuse-screen .topbar { align-items: center; gap: 6px; }
.confuse-screen .topbar h2 { flex: 1; font-size: 17px; line-height: 1.15; text-align: left; }
.collection-screen .topbar h2 { flex: 1; font-size: 19px; text-align: center; }
.collection-screen .topbar .icon-button { flex: 0 0 auto; }
.overlay { overflow-y: auto; }
@media (max-width: 460px) {
  .confuse-screen .topbar h2 { font-size: 15px; }
}

/* --- free play screen --- */
.play-screen {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: max(16px, env(safe-area-inset-top)) 20px max(28px, env(safe-area-inset-bottom));
}
.play-screen .topbar { align-items: center; gap: 6px; margin-bottom: 4px; }
.play-screen .topbar h2 { flex: 1; font-size: 19px; text-align: center; }
.play-screen .topbar .icon-button { flex: 0 0 auto; }
.play-screen .random-panel { margin-top: 12px; }
.play-screen .topics-section { margin-top: 20px; }

/* scrolling screens must not shrink their sections */
.home-screen > *, .play-screen > * { flex: 0 0 auto; }

/* --- quiz mode --- */
.probe { justify-content: flex-start; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; touch-action: pan-y; scroll-padding-block: 18px; }
.quiz-hanzi {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 4px 0 2px;
  font-family: "Noto Serif SC", serif;
  font-size: clamp(64px, 26vw, 104px);
  font-weight: 600;
  line-height: 1;
}
.quiz-hanzi[data-length="2"] { font-size: clamp(48px, 20vw, 80px); }
.quiz-hanzi[data-length="3"] { font-size: clamp(38px, 15vw, 62px); }
.quiz-speak { flex: 0 0 auto; align-self: center; margin: 0 auto 4px; }
.probe-option.is-correct { border-color: var(--green); background: var(--tint-green); color: var(--green-ink); box-shadow: inset 0 0 0 1px var(--green); }
.probe-option.is-wrong { border-color: var(--red); background: var(--tint-red); color: var(--red-dark); box-shadow: inset 0 0 0 1px var(--red); }
.probe-option:disabled { cursor: default; opacity: 1; transition: opacity .2s ease; }
.probe-option:disabled:not(.is-correct):not(.is-wrong):not(.is-picked) { opacity: .5; }
.quiz-feedback { display: flex; flex-direction: column; align-items: center; gap: 8px; margin-top: 4px; }
.quiz-image {
  width: 100%;
  max-height: min(24dvh, 180px);
  object-fit: contain;
  border-radius: 18px;
  background: var(--muted);
}
.quiz-translation { font-size: 18px; font-weight: 800; text-align: center; }
.quiz-pinyin { color: var(--ink-soft); font-size: 14px; font-weight: 600; }
.quiz-bookmark { align-self: center; cursor: pointer; }

.result-stars { display: flex; justify-content: center; gap: 8px; margin: 4px 0 16px; font-size: 38px; line-height: 1; }
.result-stars .star { color: rgba(23,59,54,.16); transition: transform .2s ease; }
.result-stars .star.is-on { color: #e8a93a; text-shadow: 0 2px 6px rgba(232,169,58,.35); }

/* ghost CTA on the dark today-card + free-play mode picker */
.menu-ghost {
  display: flex;
  width: 100%;
  min-height: 42px;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-top: 10px;
  padding: 0 18px;
  border: 1px solid rgba(255,255,255,.34);
  border-radius: 16px;
  background: rgba(255,255,255,.08);
  color: white;
  font-size: 14px;
  font-weight: 800;
  text-align: center;
  cursor: pointer;
}
.all-cards-button { justify-content: center; text-align: center; }
.all-cards-copy { text-align: center; }

@media (max-height: 740px) {
  .home-screen { padding-top: max(10px, env(safe-area-inset-top)); padding-bottom: max(10px, env(safe-area-inset-bottom)); }
  .mascot-slot--hero { width: 76px; height: 76px; }
  .home-hero { margin-block: 0 7px; }
  .stack-legend { margin-top: 5px; }
  .today-card { padding: 12px 14px; }
}
.menu-ghost:hover { background: rgba(255,255,255,.16); }
.play-mode-card { padding: 16px; margin-bottom: 12px; border: 1px solid var(--line); border-radius: 22px; background: rgba(var(--glass-rgb), .7); }
.play-mode-card .section-heading { margin-bottom: 12px; }
.play-mode-card .section-heading span { color: var(--ink-soft); font-size: 11px; font-weight: 700; }

/* ================================================================== *
 * Mobile product shell — flow redesign
 * ================================================================== */

.app-shell { max-width: 430px; }

.screen-header {
  flex: 0 0 auto;
  padding: max(12px, env(safe-area-inset-top)) 16px 8px;
  background: rgba(var(--glass-rgb), .92);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}
.screen-header h2 { flex: 1; font-size: 18px; text-align: center; }
.header-spacer { width: 44px; height: 44px; }
.screen-scroll { min-height: 0; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
.screen-footer {
  flex: 0 0 auto;
  padding: 10px 16px max(14px, env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
  background: rgba(var(--glass-rgb), .96);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}

/* Home: one clear daily action, progress, garden, then free practice. */
.home-screen { padding: max(12px, env(safe-area-inset-top)) 16px max(12px, env(safe-area-inset-bottom)); }
.home-screen .topbar { flex: 0 0 auto; }
.home-practice { margin: 8px 0 0; padding: 9px 14px; min-height: 52px; }
.home-practice > span { display: flex; min-width: 0; flex-direction: column; align-items: center; gap: 2px; }
.home-practice strong { font-size: 13px; }
.home-practice small { color: var(--ink-soft); font-size: 10px; font-weight: 600; }

/* Free practice is a single configuration flow with one start action. */
.play-screen { display: flex; height: 100%; flex-direction: column; padding: 0; overflow: hidden; }
.practice-scroll { flex: 1 1 auto; padding: 8px 16px 18px; }
.screen-intro { padding: 6px 2px 12px; }
.screen-intro h1 { margin-top: 3px; font-size: 28px; }
.screen-intro p { margin: 6px 0 0; color: var(--ink-soft); font-size: 12px; line-height: 1.45; }
.config-card {
  margin-bottom: 10px;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 20px;
  background: rgba(var(--glass-rgb), .76);
}
.config-card .section-heading { margin-bottom: 10px; }
.config-card .section-heading h2 { font-size: 17px; }
.source-control { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.source-control button {
  display: grid;
  min-height: 66px;
  place-items: center;
  gap: 2px;
  padding: 8px;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--surface);
  cursor: pointer;
}
.source-control button > span { font-family: "Noto Serif SC", serif; font-size: 23px; line-height: 1; }
.source-control button strong { font-size: 11px; }
.source-control button.is-selected { border-color: var(--red); background: var(--tint-red); box-shadow: inset 0 0 0 1px var(--red); }
.deck-size-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 12px; }
.deck-size-row > span { color: var(--ink-soft); font-size: 11px; font-weight: 700; }
.deck-size { margin: 0; }
.deck-size button { min-width: 46px; min-height: 38px; border-color: var(--line); background: var(--surface); color: var(--ink); }
.deck-size button.is-selected { border-color: var(--ink); background: var(--ink); color: var(--on-ink); }
.config-card .toggle-row { margin-top: 8px; }
.topics-section.config-card { margin-top: 0; }
.topic-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.topic-button { display: grid; min-height: 72px; grid-template-columns: 38px 1fr; grid-template-rows: auto auto; align-items: center; column-gap: 9px; padding: 9px; border-radius: 16px; }
.topic-button .topic-glyph { grid-row: 1 / 3; width: 38px; height: 38px; margin: 0; font-size: 19px; }
.topic-button strong, .topic-button small { align-self: end; }
.topic-button small { align-self: start; }
.topic-button.is-selected { border-color: var(--red); background: var(--tint-red); box-shadow: inset 0 0 0 1px var(--red); }
.selection-summary { min-height: 15px; margin: 0 0 7px; color: var(--ink-soft); font-size: 10px; font-weight: 700; text-align: center; }

/* Sessions reserve fixed chrome; only the card/probe owns overflow. */
.game-screen { padding: max(10px, env(safe-area-inset-top)) 14px max(8px, env(safe-area-inset-bottom)); }
.game-screen > .topbar { flex: 0 0 auto; }
.session-actions, .reveal-actions { flex: 0 0 auto; height: 66px; }
.probe { padding: 18px 16px 8px; }
.quiz-sticky-action {
  position: sticky;
  z-index: 7;
  bottom: -8px;
  margin-top: 12px;
  padding: 10px 0 8px;
  background: linear-gradient(180deg, rgba(255,253,247,0), var(--white) 22%);
}
.quiz-sticky-action .reveal-continue { box-shadow: 0 10px 24px rgba(23,59,54,.18); }

/* Results expose all meaningful next steps without hiding the mistake list. */
.result-screen { padding: max(18px, env(safe-area-inset-top)) 16px max(12px, env(safe-area-inset-bottom)); }
.result-summary { margin: 14px 0 12px; }
.result-actions { flex: 0 0 auto; display: grid; gap: 8px; padding-top: 10px; }
.result-actions .result-home { min-height: 50px; margin: 0; }
.result-retry { min-height: 46px; border: 1px solid var(--ink); border-radius: 16px; background: transparent; color: var(--ink); font-size: 13px; font-weight: 800; cursor: pointer; }
.result-home-link { margin: 0 auto; min-height: 34px; }

/* Settings are a full-height mobile surface with independently scrolling content. */
.settings-sheet {
  top: 0;
  bottom: 0;
  display: flex;
  max-height: none;
  height: 100%;
  flex-direction: column;
  padding: 0;
  overflow: hidden;
  border-radius: 0;
  /* Closed: below the screen, shadow included (it would shade full screens' bottom edge). */
  transform: translateY(calc(100% + 80px));
}
.settings-sheet .sheet-header {
  position: relative;
  z-index: 1;
  flex: 0 0 auto;
  margin: 0;
  padding: max(14px, env(safe-area-inset-top)) 16px 10px;
  border-bottom: 1px solid var(--line);
  background: var(--white);
}
.settings-scroll { flex: 1 1 auto; min-height: 0; padding: 16px; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
.settings-scroll fieldset { margin-bottom: 18px; }
.settings-footer { flex: 0 0 auto; padding: 10px 16px max(14px, env(safe-area-inset-bottom)); border-top: 1px solid var(--line); background: var(--white); }
.settings-footer .start-button { min-height: 50px; }

@media (min-width: 461px) {
  .app-shell { max-width: 430px; }
  .settings-sheet { top: 0; right: 0; bottom: 0; left: 0; border-radius: 0; }
}

@media (max-height: 680px) {
  .mascot-slot--hero { width: 64px; height: 64px; }
  .today-card { padding-block: 10px; }
  .today-card .menu-primary { min-height: 38px; }
  .garden-card { padding: 10px 12px; }
  .home-practice { min-height: 46px; }
}

/* ================================================================== *
 * Calm mobile ritual — product shell v2
 * ================================================================== */
:root {
  --paper: #f3eddf;
  --paper-deep: #e7ddca;
  --ink: #173b36;
  --ink-soft: #4b625d;
  --red: #df553f;
  --red-dark: #be3e2d;
  --on-red: #fff;
  --jade: #b8d1bd;
  --white: #fffdf7;
  --line: rgba(23,59,54,.14);
  /* Surfaces and tints; dark values below. */
  --on-ink: #fff;
  --surface: #f5f0e7;
  --muted: #eee5d5;
  --tint-red: #fbe9e4;
  --tint-green: #e2f3e7;
  --green: #2f8a5a;
  --green-ink: #1f6440;
  --stack-mastered: #2f8a5a;
  --stack-remembered: #9dc9a6;
  /* The Progress chart's bands: the garden's hues, stepped apart to stay distinct for colour-blind readers. */
  --growth-mastered: #16804a;
  --growth-remembered: #6cbd84;
  --growth-learning: #e07c38;
  --stack-learning: #efb88e;
  --strong: var(--ink);
  --on-strong: #fff;
  /* rgb triples for translucent surfaces: rgba(var(--glass-rgb), .7) */
  --glass-rgb: 255, 253, 247;
  --jade-rgb: 184, 209, 189;
  --hit: #2f6659;
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --paper: #17251e;
  --paper-deep: #293e31;
  --ink: #e5ebd9;
  --ink-soft: #a1af9e;
  --red: #e38a68;
  --red-dark: #eba183;
  /* White on the lighter dark-mode red is under 3:1; ink reads at 6:1. */
  --on-red: #17251e;
  --jade: #91ac7f;
  --white: #203329;
  --line: rgba(229,235,217,.14);
  --on-ink: #17251e;
  --surface: #223629;
  --muted: #2a3f33;
  --tint-red: rgba(227,138,104,.18);
  --tint-green: rgba(126,196,146,.18);
  --green: #7ec492;
  --green-ink: #b6e3c1;
  --growth-mastered: #237f4d;
  --growth-remembered: #5cb47d;
  --growth-learning: #c9692a;
  --stack-mastered: #7ec492;
  --stack-remembered: #4f7a5c;
  --stack-learning: #b77a55;
  /* Big emphasised cards (today's review) stay dark green, lit a step above the page. */
  --strong: #2b4a3c;
  --on-strong: #eef3e6;
  --glass-rgb: 38, 58, 47;
  --jade-rgb: 96, 138, 98;
  --hit: #9fd6ae;
}
:root[data-theme="dark"] body { background: #111d17; }
:root[data-theme="dark"] .app-shell {
  background: radial-gradient(circle at 86% 4%, rgba(227,138,104,.1), transparent 30%), linear-gradient(155deg, #1b2c23, var(--paper));
}
:root[data-theme="dark"] .screen-header,
:root[data-theme="dark"] .screen-footer,
:root[data-theme="dark"] .bottom-nav { background: rgba(23,37,30,.94); }
:root[data-theme="dark"] .settings-sheet,
:root[data-theme="dark"] .settings-sheet .sheet-header,
:root[data-theme="dark"] .settings-footer { background: var(--white); }
:root[data-theme="dark"] .segmented button { background: var(--paper); color: var(--ink); }
:root[data-theme="dark"] .segmented button.is-selected { background: rgba(227,138,104,.2); color: var(--ink); }
:root[data-theme="dark"] .close-button { background: var(--paper-deep); color: var(--ink); }

/* The tab bar's height, reserved under every tabbed view. One value for both,
   so no strip of background shows between a view and the bar. */
.app-shell { --nav-h: calc(67px + env(safe-area-inset-bottom)); padding-bottom: var(--nav-h); }
.view { height: 100%; min-height: 0; }
.game-screen, .result-screen, .detail-screen { height: 100dvh; }
/* In the framed desktop shell (≥461px, 40px shorter than the viewport) full
   screens must fit the frame, or their bottom actions are cut off. */
@media (min-width: 461px) { .game-screen, .result-screen, .detail-screen { height: 100%; } }
.home-screen { padding-bottom: 16px; }
.home-eyebrow { display: block; color: var(--ink-soft); font-size: 9px; font-weight: 800; letter-spacing: .14em; }
.home-hero { margin-top: 4px; }
.mascot-slot--hero { width: 112px; height: 112px; margin-bottom: 1px; }
.today-card { background: var(--strong); border-radius: 24px; }
.today-card .menu-primary { background: var(--red); color: var(--on-red); justify-content: center; }
.garden-card, .daily-word, .config-card, .activity-card, .growth-card, .week-card, .hard-card { box-shadow: 0 8px 28px -22px rgba(41,73,59,.28); }
.daily-word {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  margin-top: 10px; padding: 16px 18px; border: 1px solid var(--line); border-radius: 20px;
  background: var(--white);
}
.daily-word h2 { margin: 5px 0 1px; font-size: 18px; }
.daily-word h2 span { margin-right: 5px; font: 30px "Noto Serif SC", serif; }
.daily-word p { margin: 0; color: var(--ink-soft); font-size: 10px; }
.daily-word__open { width: 44px; height: 44px; flex: 0 0 auto; border: 0; border-radius: 14px; background: var(--paper-deep); color: var(--ink); font-size: 20px; }

.bottom-nav {
  position: absolute; z-index: 20; right: 0; bottom: 0; left: 0; display: grid;
  height: var(--nav-h); grid-template-columns: repeat(4,1fr); padding: 7px 10px calc(7px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line); background: rgba(var(--glass-rgb), .94);
  backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px);
}
.bottom-nav button { position: relative; display: flex; min-height: 52px; flex-direction: column; align-items: center; justify-content: center; gap: 3px; border: 0; border-radius: 14px; background: transparent; color: var(--ink-soft); }
.bottom-nav button > span { display: grid; width: 34px; height: 25px; place-items: center; border-radius: 10px; font: 19px "Noto Serif SC", serif; }
.bottom-nav button > small { font-size: 9px; font-weight: 700; }
.bottom-nav button.is-active { color: var(--red-dark); }
.bottom-nav button.is-active > span { background: rgba(184,88,57,.12); }
.app-shell:has(.game-screen:not([hidden])) .bottom-nav,
.app-shell:has(.result-screen:not([hidden])) .bottom-nav,
.app-shell:has(.detail-screen:not([hidden])) .bottom-nav,
.app-shell:has(.onboarding:not([hidden])) .bottom-nav { display: none; }
/* Settings end with a close button; the nav would sit on top of it. */
.app-shell:has(.settings-sheet.is-open) .bottom-nav { display: none; }
.app-shell:has(.game-screen:not([hidden])),
.app-shell:has(.result-screen:not([hidden])),
.app-shell:has(.detail-screen:not([hidden])),
.app-shell:has(.onboarding:not([hidden])) { padding-bottom: 0; }

.quiz-direction-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 7px; }
.quiz-direction-grid button { display: flex; min-height: 62px; flex-direction: column; justify-content: center; padding: 8px 10px; border: 1px solid var(--line); border-radius: 15px; background: var(--paper); text-align: left; }
.quiz-direction-grid button:first-child { grid-column: 1 / -1; min-height: 52px; align-items: center; }
.quiz-direction-grid b { font: 15px "Noto Serif SC", serif; }
.quiz-direction-grid span { margin-top: 2px; color: var(--ink-soft); font-size: 9px; font-weight: 700; }
.quiz-direction-grid button.is-selected { border-color: var(--red); background: rgba(184,88,57,.1); box-shadow: inset 0 0 0 1px var(--red); }
.quiz-hanzi.quiz-prompt--text { font-family: "Manrope", system-ui, sans-serif; font-size: clamp(24px, 8vw, 38px); line-height: 1.25; text-align: center; }
.probe-option--hanzi { font-family: "Noto Serif SC", serif; font-size: 28px; }

.stats-screen { display: flex; flex-direction: column; padding: max(14px, env(safe-area-inset-top)) 16px 10px; }
.stats-header { flex: 0 0 auto; }
.stats-header h1 { margin: 2px 0 0; font-size: 28px; }
.stats-scroll { flex: 1; min-height: 0; overflow-y: auto; padding: 12px 0 18px; }
.activity-card, .growth-card, .week-card, .hard-card { margin-top: 10px; padding: 17px; border: 1px solid var(--line); border-radius: 20px; background: var(--white); }
.growth-card { margin-top: 0; }
.growth-card__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.growth-card__head h2 { font-size: 21px; }
.growth-card__head span { display: block; margin-top: 3px; color: var(--ink-soft); font-size: 11px; font-weight: 700; }
.growth-card__gain { flex-shrink: 0; padding: 5px 10px; border-radius: 99px; background: var(--tint-green); color: var(--green-ink); font-size: 13px; font-weight: 800; white-space: nowrap; }
.growth-card__empty { margin: 14px 0 4px; color: var(--ink-soft); font-size: 12px; }
.growth-card__eta { margin: 10px 0 0; padding-top: 10px; border-top: 1px solid var(--line); color: var(--ink); font-size: 12px; font-weight: 700; }
.growth-chart { position: relative; margin-top: 8px; }
.growth-chart svg { display: block; width: 100%; height: auto; overflow: visible; touch-action: pan-y; }
.growth-chart__area--mastered { fill: var(--growth-mastered); }
.growth-chart__area--remembered { fill: var(--growth-remembered); }
.growth-chart__area--learning { fill: var(--growth-learning); }
.growth-chart__edge { fill: none; stroke: var(--white); stroke-width: 1.5; stroke-linejoin: round; }
.growth-chart__grid { stroke: var(--line); stroke-dasharray: 2 3; }
.growth-chart__base { stroke: var(--line); }
.growth-chart__max, .growth-chart__day { fill: var(--ink-soft); font-size: 10px; font-weight: 700; }
.growth-chart__day--end { text-anchor: end; }
.growth-chart__cursor { stroke: var(--ink); stroke-width: 1; opacity: .5; }
.growth-chart__dot { fill: var(--ink); stroke: var(--white); stroke-width: 2; }
.growth-chart__tip { position: absolute; top: -4px; margin: 0; padding: 5px 8px; border-radius: 8px; background: var(--ink); color: var(--white); font-size: 10px; font-weight: 700; white-space: nowrap; pointer-events: none; }
.growth-chart__tip[data-side="right"] { transform: translateX(8px); }
.growth-chart__tip[data-side="left"] { transform: translateX(calc(-100% - 8px)); }
.growth-legend { margin-top: 6px; }
.growth-legend__item--mastered i { background: var(--growth-mastered); }
.growth-legend__item--remembered i { background: var(--growth-remembered); }
.growth-legend__item--learning i { background: var(--growth-learning); }
.week-rows { display: grid; gap: 2px; }
.week-row { display: grid; grid-template-columns: 1fr auto 58px; align-items: baseline; gap: 10px; padding: 7px 0; border-top: 1px solid var(--line); font-size: 13px; }
.week-row:first-child { border-top: 0; padding-top: 0; }
.week-row span { color: var(--ink-soft); font-weight: 700; }
.week-row b { font-size: 17px; letter-spacing: -.02em; }
.week-row small { color: var(--ink-soft); font-size: 11px; font-weight: 700; text-align: right; }
.week-row small.is-up { color: var(--green-ink); }
.activity-heatmap { display: grid; grid-template-rows: repeat(7, 1fr); grid-auto-flow: column; gap: 3px; }
.heat-cell { aspect-ratio: 1; border-radius: 3px; background: var(--paper-deep); }
.heat-cell.is-future { visibility: hidden; }
.heat-cell.is-today { box-shadow: inset 0 0 0 1.5px var(--ink); }
.heat-cell[data-level="1"] { background: #d6e1cb; }.heat-cell[data-level="2"] { background: #adc39d; }.heat-cell[data-level="3"] { background: #7e9e70; }.heat-cell[data-level="4"] { background: #55784f; }
.hard-list { display: flex; flex-wrap: wrap; gap: 8px; }
.hard-list button { display: grid; min-width: 52px; height: 56px; padding: 0 8px; place-items: center; align-content: center; gap: 1px; border: 1px solid var(--line); border-radius: 14px; background: var(--surface); color: var(--ink); cursor: pointer; }
.hard-list b { font-family: "Noto Serif SC", serif; font-size: 24px; font-weight: 600; line-height: 1; white-space: nowrap; }
.hard-list small { color: var(--ink-soft); font-size: 9px; font-weight: 700; white-space: nowrap; }
.achievements-card__next { margin-top: 2px; }

.onboarding { position: absolute; z-index: 50; inset: 0; display: flex; flex-direction: column; background: var(--paper); }
.onboarding__header { display: flex; min-height: 70px; align-items: center; justify-content: space-between; padding: max(12px, env(safe-area-inset-top)) 20px 8px; }
.onboarding__progress { display: flex; gap: 6px; padding: 5px 20px; }
.onboarding__progress span { height: 5px; flex: 1; border-radius: 5px; background: var(--paper-deep); }
.onboarding__progress span.is-done { background: var(--red); }
.onboarding__body { display: flex; flex: 1; min-height: 0; flex-direction: column; align-items: center; justify-content: center; padding: 10px 28px; text-align: center; }
.onboarding__mascot { width: min(230px, 56vw); height: min(230px, 29dvh); margin-bottom: 12px; }
/*
 * The forgetting curve (memory-curve.js). Everything is drawn in its final
 * state and animates from hidden (fill-mode both), so reduced motion simply
 * shows the finished graph.
 */
.onboarding__mascot.memory-curve { position: relative; display: block; width: min(340px, 88vw); height: auto; }
.memory-curve__plot { position: relative; }
.memory-curve svg { display: block; width: 100%; height: auto; overflow: visible; }
.memory-curve__frame { fill: none; stroke: var(--line); stroke-width: 2; stroke-linecap: round; }
.memory-curve__grid { stroke: var(--red); stroke-width: 1.5; stroke-dasharray: 4 5; opacity: .35; }
.memory-curve__axis { fill: var(--ink-soft); font-size: 9px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; }
.memory-curve__tick { stroke: var(--line); stroke-width: 2; }
.memory-curve__day { fill: var(--ink-soft); font-size: 9.5px; font-weight: 800; text-anchor: middle; }
/* Each stretch between reviews: fragile red at first, bold gold once mastered. */
.memory-curve { --curve-0: #e0553f; --curve-1: #ef8b35; --curve-2: #a7b53a; --curve-3: #2f8a5a; --curve-4: #e8a917; }
:root[data-theme="dark"] .memory-curve { --curve-3: #7ec492; --curve-4: #f4c64f; }
.memory-curve__line { fill: none; stroke: var(--curve); stroke-width: var(--weight); stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: var(--len); animation: curve-draw var(--dur) linear var(--delay) both; }
.memory-curve__line--0 { --curve: var(--curve-0); --weight: 3; }
.memory-curve__line--1 { --curve: var(--curve-1); --weight: 3.5; }
.memory-curve__line--2 { --curve: var(--curve-2); --weight: 4; }
.memory-curve__line--3 { --curve: var(--curve-3); --weight: 4.5; }
.memory-curve__line--4 { --curve: var(--curve-4); --weight: 6; filter: drop-shadow(0 0 4px rgba(232,169,23,.55)); }
.memory-curve__dot { stroke: var(--white); stroke-width: 2.5; animation: curve-pop .45s cubic-bezier(.3,1.6,.5,1) var(--delay) both; }
.memory-curve__dot--1 { fill: var(--curve-1); } .memory-curve__dot--2 { fill: var(--curve-2); } .memory-curve__dot--3 { fill: var(--curve-3); } .memory-curve__dot--4 { fill: var(--curve-4); }
/* State badges stand on their review points. */
.memory-curve__badge { position: absolute; padding: 3px 7px; border-radius: 99px; font-size: 10.5px; font-weight: 800; white-space: nowrap; box-shadow: 0 3px 8px rgba(37,45,34,.12); translate: -50% calc(-100% - 9px); animation: curve-badge .45s cubic-bezier(.3,1.6,.5,1) var(--delay) both; }
.memory-curve__badge--1 { background: #fde3c8; color: #7a3a0c; }
.memory-curve__badge--3 { background: #d3ecdc; color: #1f6440; }
.memory-curve__badge--4 { background: #f6c64a; color: #4c2a05; }
/* On top of the Mastered badge (its left/top are the day-30 point). */
.memory-curve__sticker { position: absolute; --sticker: 56px; height: 56px; margin: calc(-92px - var(--pad)) 0 0 calc(-28px - var(--pad)); }
@keyframes curve-draw { 0% { stroke-dashoffset: var(--len); opacity: 0; } 1% { opacity: 1; } 100% { stroke-dashoffset: 0; } }
@keyframes curve-pop { from { opacity: 0; scale: .2; } }
@keyframes curve-badge { from { opacity: 0; scale: .4; } }
@media (prefers-reduced-motion: reduce) { .memory-curve__line, .memory-curve__dot, .memory-curve__badge { animation: none; } }
.onboarding__body h1 { max-width: 340px; margin: 12px 0 10px; font-size: 32px; line-height: 1.12; letter-spacing: -.05em; }
.onboarding__body > p { max-width: 330px; margin: 0; color: var(--ink-soft); font-size: 14px; line-height: 1.6; }
.onboarding__demo { display: flex; min-width: 230px; margin-top: 24px; align-items: center; justify-content: center; gap: 14px; padding: 14px 16px 14px 22px; border: 1px solid var(--line); border-radius: 22px; background: var(--white); }
.onboarding__demo .ob-tea { font: 58px "Noto Serif SC", serif; }
.ob-tea-reading { display: grid; justify-items: start; gap: 1px; text-align: left; }
.onboarding__demo b { font-size: 20px; }.onboarding__demo small { color: var(--ink-soft); font-size: 14px; font-weight: 700; }
.onboarding__footer { padding: 12px 20px max(16px, env(safe-area-inset-bottom)); }
.onboarding__footer .menu-primary { justify-content: center; background: var(--red); color: var(--on-red); }
.onboarding__footer .menu-primary:disabled { background: var(--muted); color: var(--ink-soft); }

/*
 * Onboarding scenes (onboarding-scenes.js). Each step replays its entrance:
 * the body's children rise in one after another. Decorations animate from
 * hidden with fill-mode both, so reduced motion shows the finished scene.
 */
.onboarding__body { justify-content: safe center; overflow-y: auto; }
.onboarding__body.is-entering > * { animation: ob-enter .5s cubic-bezier(.2,.8,.25,1) both; }
.onboarding__body.is-entering > :nth-child(2) { animation-delay: .07s; }
.onboarding__body.is-entering > :nth-child(3) { animation-delay: .12s; }
.onboarding__body.is-entering > :nth-child(n+4) { animation-delay: .18s; }
.onboarding__body.is-entering > :nth-child(n+6) { animation-delay: .26s; }
.onboarding__body.is-entering .onboarding__stage:is([data-scene="bao"], [data-scene="year"]) .mascot { animation: ob-bao-hop .75s cubic-bezier(.3,1.4,.5,1) both; transform-origin: 50% 90%; }
@keyframes ob-enter { from { opacity: 0; transform: translateY(14px); } }
@keyframes ob-bao-hop { 0% { opacity: 0; transform: translateY(18px) scale(.8, .86); } 55% { opacity: 1; transform: translateY(-10px) scale(.96, 1.05); } 78% { transform: scale(1.05, .95); } 100% { transform: none; } }
#onboardingProgress span.is-current { position: relative; overflow: hidden; background: var(--paper-deep); }
#onboardingProgress span.is-current::after { content: ""; position: absolute; inset: 0; border-radius: inherit; background: var(--red); transform-origin: left; animation: ob-fill .55s .1s ease-out both; }
@keyframes ob-fill { from { transform: scaleX(0); } }

.onboarding__stage { position: relative; display: flex; justify-content: center; }
.onboarding__fx { position: absolute; inset: 0; pointer-events: none; }
.onboarding__stage[data-scene="year"] .onboarding__mascot { width: 118px; height: 118px; margin-bottom: 0; }

/* Step 1: steam rises off the bun, and Bao says 你好. */
.ob-steam { position: absolute; top: 2%; left: calc(38% + var(--i) * 10%); width: 16px; height: 46px; overflow: visible; fill: none; stroke: var(--ink-soft); stroke-width: 3; stroke-linecap: round; opacity: 0; animation: ob-steam 2.8s calc(.6s + var(--i) * .55s) ease-out infinite; }
@keyframes ob-steam { 0% { opacity: 0; transform: translateY(12px) scaleY(.6); } 30% { opacity: .38; } 100% { opacity: 0; transform: translateY(-26px) scaleY(1.1); } }
.ob-hello { position: absolute; top: 12%; right: calc(50% - min(150px, 40vw)); padding: 6px 11px; border: 1px solid var(--line); border-radius: 14px 14px 14px 4px; background: var(--white); color: var(--red); font: 800 17px "Noto Serif SC", serif; box-shadow: 0 10px 22px -14px rgba(41,73,59,.5); animation: ob-pop .5s .55s cubic-bezier(.3,1.6,.5,1) both, ob-float 3.2s 1.1s ease-in-out infinite; }
@keyframes ob-pop { from { opacity: 0; scale: .3; } }
@keyframes ob-float { 50% { translate: 0 -4px; } }

/* Step 2: 茶 is inked in, and the tea steams. */
.onboarding__demo { position: relative; }
.ob-tea { position: relative; }
.onboarding__demo:not([hidden]) .ob-tea { animation: ob-ink 1s .3s cubic-bezier(.3,.7,.3,1) both; }
.onboarding__demo:not([hidden]) b, .onboarding__demo:not([hidden]) .ob-tea-reading small { animation: ob-enter .45s both; }
.onboarding__demo:not([hidden]) b { animation-delay: .9s; }
.onboarding__demo:not([hidden]) .ob-tea-reading small { animation-delay: 1.05s; }
/* Negative insets leave room for the steam above the glyph. */
@keyframes ob-ink { from { clip-path: inset(-150% 100% -20% -20%); filter: blur(4px); } 60% { filter: blur(0); } to { clip-path: inset(-150% -20% -20% -20%); } }
.ob-tea-steam { position: absolute; bottom: 88%; left: 50%; width: 0; height: 0; }
.ob-tea-steam svg { position: absolute; bottom: 0; left: calc(var(--x) - 6px); width: 12px; height: 34px; overflow: visible; fill: none; stroke: var(--ink-soft); stroke-width: 3; stroke-linecap: round; opacity: 0; animation: ob-steam 2.6s var(--d) ease-out infinite; }
.ob-tea-steam svg:nth-child(1) { --x: -12px; --d: 1.2s; }
.ob-tea-steam svg:nth-child(2) { --x: 2px; --d: 1.8s; }
.ob-tea-steam svg:nth-child(3) { --x: 15px; --d: 2.4s; }

/* The tea card's play button: it pulses until heard, and shows sound waves while playing. */
.ob-speak { position: relative; display: grid; flex: none; place-items: center; width: 50px; height: 50px; border: 0; border-radius: 50%; background: linear-gradient(135deg, #fa8466, #cf4934); color: #fff; box-shadow: 0 6px 16px rgba(223,85,63,.34); cursor: pointer; transition: transform .15s; }
.ob-speak:active { transform: scale(.93); }
.ob-speak svg { width: 25px; height: 25px; }
.ob-speak::before { content: ""; position: absolute; inset: -5px; border: 2px solid var(--red); border-radius: 50%; opacity: 0; animation: ob-speak-ring 1.9s 1.3s ease-out infinite; pointer-events: none; }
.onboarding__demo.is-heard .ob-speak::before { animation: none; }
.onboarding__demo:not([hidden]) .ob-speak { animation: ob-pop .5s 1.1s cubic-bezier(.3,1.6,.5,1) both; }
.ob-speak.is-playing .ob-wave { animation: ob-wave .7s ease-in-out infinite; }
.ob-speak.is-playing .ob-wave--2 { animation-delay: .18s; }
@keyframes ob-speak-ring { 0% { opacity: .75; transform: scale(.9); } 100% { opacity: 0; transform: scale(1.4); } }
@keyframes ob-wave { 50% { opacity: .2; } }
.ob-spark { position: absolute; left: var(--x); top: var(--y); width: var(--s, 12px); height: var(--s, 12px); background: #ffc93c; clip-path: polygon(50% 0, 61% 39%, 100% 50%, 61% 61%, 50% 100%, 39% 61%, 0 50%, 39% 39%); opacity: 0; animation: sticker-spark 2.4s var(--spark-delay, .85s) ease-in-out infinite; pointer-events: none; }

/* Step 5: the pace chart (pace-chart.js). */
.onboarding__mascot.pace-chart { position: relative; display: block; width: min(340px, 88vw); height: auto; margin-bottom: 4px; }
.pace-chart__plot { position: relative; margin-top: 16px; }
.pace-chart svg { display: block; width: 100%; height: auto; overflow: visible; }
.pace-chart__band--1 { fill: var(--tint-red); opacity: .7; }
.pace-chart__band--2 { fill: var(--tint-green); opacity: .7; }
.pace-chart__level { stroke: var(--ink-soft); stroke-width: 1.2; stroke-dasharray: 3 4; opacity: .4; }
.pace-chart__band-label { fill: var(--ink-soft); font-size: 9px; font-weight: 900; letter-spacing: .04em; text-anchor: end; }
.pace-chart__frame { fill: none; stroke: var(--line); stroke-width: 2; stroke-linecap: round; }
.pace-chart__axis { fill: var(--ink-soft); font-size: 9px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; }
.pace-chart__tick { stroke: var(--line); stroke-width: 2; }
.pace-chart__month { fill: var(--ink-soft); font-size: 9.5px; font-weight: 800; text-anchor: middle; }
.pace-chart__line { fill: none; stroke-linecap: round; stroke-linejoin: round; }
.pace-chart__line--other { stroke: var(--ink-soft); stroke-width: 2.5; opacity: .22; }
.pace-chart__line--chosen { stroke: var(--red); stroke-width: 5; stroke-dasharray: 1; filter: drop-shadow(0 3px 5px rgba(223,85,63,.35)); animation: pace-draw var(--dur) cubic-bezier(.4,.1,.3,1) var(--delay) both; }
@keyframes pace-draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
.pace-chart__dot { fill: var(--white); stroke: var(--red); stroke-width: 3; animation: curve-pop .45s cubic-bezier(.3,1.6,.5,1) var(--delay) both; }
.pace-chart__end { fill: var(--red); font-size: 12px; font-weight: 900; text-anchor: end; animation: curve-pop .45s cubic-bezier(.3,1.6,.5,1) var(--delay) both; }
.pace-chart__badge { position: absolute; padding: 3px 8px; border-radius: 99px; background: var(--ink); color: var(--paper); font-size: 10.5px; font-weight: 800; white-space: nowrap; box-shadow: 0 3px 8px rgba(37,45,34,.18); translate: -50% calc(-100% - 9px); animation: curve-badge .45s cubic-bezier(.3,1.6,.5,1) var(--delay) both; }

/* Step 5: minutes a day, and Bao's comment on the choice. */
.ob-pace { width: min(340px, 100%); margin-top: 14px; }
.ob-pace__options { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.ob-pace__options button { display: grid; justify-items: center; gap: 1px; padding: 9px 4px 8px; border: 1px solid var(--line); border-radius: 16px; background: var(--white); color: var(--ink); font: inherit; cursor: pointer; transition: border-color .2s, background .2s, transform .2s cubic-bezier(.3,1.6,.5,1); }
.ob-pace__options b { font-size: 24px; line-height: 1; letter-spacing: -.04em; }
.ob-pace__options span { color: var(--ink-soft); font-size: 11px; font-weight: 800; }
.ob-pace__options small { color: var(--ink-soft); font-size: 10.5px; font-weight: 700; }
.ob-pace__options button[aria-checked="true"] { border-color: var(--red); background: var(--tint-red); box-shadow: inset 0 0 0 1px var(--red); transform: translateY(-3px); }
.ob-pace__options button[aria-checked="true"] b { color: var(--red); }
.ob-pace__bao { display: flex; align-items: center; gap: 10px; margin-top: 12px; text-align: left; }
.ob-pace__mascot { flex: none; width: 64px; height: 64px; }
.ob-pace__mascot .mascot.is-reacting { animation: ob-bao-hop .6s cubic-bezier(.3,1.4,.5,1); transform-origin: 50% 90%; }
.ob-pace__line { flex: 1; min-height: 3.9em; margin: 0; padding: 9px 12px; border: 1px solid var(--line); border-radius: 16px 16px 16px 5px; background: var(--white); color: var(--ink); font-size: 13px; font-weight: 700; line-height: 1.38; }
.ob-pace__line.is-reacting { animation: result-bao-line .35s ease-out; }

/* Step 6: a year of five-minute days. */
.ob-year { width: min(330px, 100%); margin: 2px 0 12px; }
.ob-year__count b { display: block; color: var(--red); font-size: 44px; line-height: 1; letter-spacing: -.05em; font-variant-numeric: tabular-nums; }
.ob-year__count small { color: var(--ink-soft); font-size: 12px; font-weight: 800; }
.ob-year__calendar { position: relative; margin-top: 30px; }
.ob-year__grid { display: grid; grid-template-rows: repeat(7, 1fr); grid-template-columns: repeat(var(--weeks), 1fr); grid-auto-flow: column; gap: 1.5px; }
.ob-year__grid i { aspect-ratio: 1; border-radius: 1.5px; background: var(--c); animation: ob-cell .4s calc(.25s + var(--w) * 34ms) ease-out both; }
.ob-year__grid i[data-level="1"] { --c: #d6e1cb; }
.ob-year__grid i[data-level="2"] { --c: #adc39d; }
.ob-year__grid i[data-level="3"] { --c: #7e9e70; }
.ob-year__grid i[data-level="4"] { --c: #e8a917; }
:root[data-theme="dark"] .ob-year__grid i[data-level="1"] { --c: #3b5646; }
:root[data-theme="dark"] .ob-year__grid i[data-level="2"] { --c: #56785f; }
:root[data-theme="dark"] .ob-year__grid i[data-level="3"] { --c: #7ea484; }
:root[data-theme="dark"] .ob-year__grid i[data-level="4"] { --c: #f4c64f; }
@keyframes ob-cell { from { background: var(--paper-deep); opacity: .4; scale: .3; } }
.ob-year__pin { position: absolute; bottom: calc(100% + 6px); padding: 3px 8px; border-radius: 99px; background: #f6c64a; color: #4c2a05; font-size: 10.5px; font-weight: 900; white-space: nowrap; translate: -50% 0; animation: curve-badge .45s calc(.35s + var(--w) * 34ms) cubic-bezier(.3,1.6,.5,1) both; }
.ob-year__pin::after { content: ""; position: absolute; top: 100%; left: 50%; width: 2px; height: 6px; background: #f6c64a; translate: -50% 0; }
.ob-year__ends { display: flex; justify-content: space-between; margin-top: 5px; color: var(--ink-soft); font-size: 9.5px; font-weight: 800; }
.ob-confetti { position: absolute; left: 50%; top: 50%; width: 7px; height: 12px; margin: -6px 0 0 -3.5px; border-radius: 2px; background: var(--c); opacity: 0; animation: ob-confetti 1.4s var(--d) cubic-bezier(.15,.7,.3,1) both; }
.ob-confetti--round { width: 8px; height: 8px; margin: -4px 0 0 -4px; border-radius: 50%; }
@keyframes ob-confetti { 0% { opacity: 1; transform: scale(.3); } 75% { opacity: 1; } 100% { opacity: 0; transform: translate(var(--dx), calc(var(--dy) + 26px)) rotate(var(--r)) scale(1); } }

/*
 * Scenes standing in for Bao (onboarding-scenes.js): writing, a quiz, the
 * four ways, the garden and the mock test. Part and method colours are
 * tokens, redefined for dark mode.
 */
:root {
  --ob-part-0: #3f8f5f; --ob-part-0-tint: #e4f1e7;
  --ob-part-1: #df553f; --ob-part-1-tint: #fbe7e2;
  --ob-part-2: #c68a1c; --ob-part-2-tint: #f8ecd2;
  --ob-method-0: #df553f; --ob-method-0-tint: #fbe7e2;
  --ob-method-1: #3e6f91; --ob-method-1-tint: #e2edf5;
  --ob-method-2: #3f8f5f; --ob-method-2-tint: #e4f1e7;
  --ob-method-3: #c68a1c; --ob-method-3-tint: #f8ecd2;
  --ob-gold: #c68a1c;
}
:root[data-theme="dark"] {
  --ob-part-0: #7ec492; --ob-part-0-tint: rgba(126,196,146,.16);
  --ob-part-1: #e38a68; --ob-part-1-tint: rgba(227,138,104,.16);
  --ob-part-2: #f0c35a; --ob-part-2-tint: rgba(240,195,90,.16);
  --ob-method-0: #e38a68; --ob-method-0-tint: rgba(227,138,104,.16);
  --ob-method-1: #8fb8d8; --ob-method-1-tint: rgba(143,184,216,.16);
  --ob-method-2: #7ec492; --ob-method-2-tint: rgba(126,196,146,.16);
  --ob-method-3: #f0c35a; --ob-method-3-tint: rgba(240,195,90,.16);
  --ob-gold: #f0c35a;
}
.onboarding__stage:has(> .ob-scene:not([hidden])) { width: 100%; }
.onboarding__stage:has(> .ob-scene:not([hidden])) .onboarding__mascot { display: none; }
.ob-scene { position: relative; width: min(330px, 100%); margin: 0 auto 16px; }

/* Writing: the brush reveals each stroke along its median; parts pop in as they are finished. */
.ob-write { display: flex; flex-direction: column; align-items: center; }
.ob-write__box { position: relative; width: min(210px, 29dvh); aspect-ratio: 1; border: 1.5px solid rgba(223,85,63,.45); border-radius: 18px; background: var(--white); box-shadow: 0 16px 30px -22px rgba(41,73,59,.6); }
.ob-write__grid { position: absolute; inset: 0; width: 100%; height: 100%; border-radius: inherit; fill: none; stroke: var(--red); stroke-width: .5; stroke-opacity: .3; stroke-dasharray: 2.2 1.8; clip-path: inset(0 round 16px); }
.ob-write__glyph { position: absolute; inset: 9%; width: 82%; height: 82%; overflow: visible; }
.ob-write__ghost { fill: var(--paper-deep); }
.ob-write__stroke { fill: none; stroke: var(--c); stroke-width: 200; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1 1; stroke-dashoffset: 0; animation: ob-stroke .42s var(--at) cubic-bezier(.45,.05,.55,.95) both; }
@keyframes ob-stroke { 0% { opacity: 0; stroke-dashoffset: 1; } 1% { opacity: 1; } 100% { stroke-dashoffset: 0; } }
.ob-write__replay { position: absolute; right: -10px; bottom: -10px; display: grid; place-items: center; width: 40px; height: 40px; border: 1px solid var(--line); border-radius: 50%; background: var(--white); color: var(--ink-soft); box-shadow: 0 6px 14px -8px rgba(41,73,59,.5); cursor: pointer; }
.ob-write__replay svg { width: 18px; height: 18px; }
.ob-write__replay:active { transform: scale(.93); }
.ob-write__parts { display: flex; align-items: center; justify-content: center; gap: 6px; margin-top: 14px; }
.ob-part { display: flex; align-items: center; gap: 6px; animation: ob-part .5s var(--at) cubic-bezier(.3,1.5,.5,1) both; }
.ob-part i { color: var(--ink-soft); font-size: 18px; font-style: normal; font-weight: 800; }
.ob-part__chip { display: grid; justify-items: center; min-width: 66px; padding: 5px 8px 6px; border: 1.5px solid var(--c); border-radius: 16px; background: var(--t); }
.ob-part b { color: var(--c); font: 700 26px/1.15 "Noto Serif SC", serif; }
.ob-part small { color: var(--ink-soft); font-size: 11px; font-weight: 800; }
@keyframes ob-part { from { opacity: 0; transform: translateY(12px) scale(.7); } }

/* Quiz */
.ob-quiz { display: grid; gap: 9px; }
.ob-quiz__prompt { display: grid; justify-items: center; padding: 10px 0 8px; border: 1px solid var(--line); border-radius: 22px; background: var(--white); box-shadow: 0 16px 34px -24px rgba(41,73,59,.6); }
.ob-quiz__prompt small { color: var(--ink-soft); font-size: 12px; font-weight: 800; }
.ob-quiz__prompt span { font: 64px/1.15 "Noto Serif SC", serif; }
.ob-quiz__options { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.ob-quiz .probe-option { position: relative; min-height: 48px; color: var(--ink); }
.ob-quiz .probe-option.is-wrong { animation: ob-shake .4s; }
.ob-quiz .probe-option.is-correct { animation: ob-right .5s cubic-bezier(.3,1.6,.5,1); }
.ob-quiz.is-solved .probe-option:disabled:not(.is-correct) { opacity: .45; }
.ob-quiz__confetti { position: absolute; z-index: 2; width: 0; height: 0; pointer-events: none; }
.ob-quiz__feedback { min-height: 1.4em; margin: 0; color: var(--ink-soft); font-size: 13px; font-weight: 800; }
.ob-quiz__feedback.is-good { color: var(--green-ink); animation: ob-enter .3s both; }
.ob-quiz__feedback.is-bad { color: var(--red-dark); animation: ob-enter .3s both; }
@keyframes ob-shake { 20%, 60% { transform: translateX(-6px); } 40%, 80% { transform: translateX(6px); } }
@keyframes ob-right { 50% { transform: scale(1.06); } }

/* The four ways: each lights up, links to the character and fills a quarter of its memory ring. */
.ob-methods { aspect-ratio: 300 / 220; }
.ob-methods__links { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.ob-methods__links path { fill: none; stroke: var(--c); stroke-width: 2; stroke-linecap: round; stroke-opacity: .55; stroke-dasharray: 1 1; animation: ob-link .45s calc(.45s + var(--i) * .55s) ease-out both; }
@keyframes ob-link { from { stroke-dashoffset: 1; } }
.ob-methods__core { position: absolute; top: 50%; left: 50%; display: grid; place-items: center; align-content: center; width: 40%; aspect-ratio: 1; border-radius: 50%; background: var(--white); box-shadow: 0 14px 30px -18px rgba(41,73,59,.6); translate: -50% -50%; }
.ob-methods__core svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.ob-methods__core circle { fill: none; stroke-width: 9; }
.ob-methods__track { stroke: var(--paper-deep); }
.ob-methods__arc { stroke: var(--c); stroke-linecap: round; stroke-dasharray: 21 79; transform-box: fill-box; transform-origin: center; animation: ob-arc .5s calc(.7s + var(--i) * .55s) ease-out both; }
@keyframes ob-arc { from { stroke-dasharray: 0 100; } }
.ob-methods__glyph { position: relative; font: 46px/1 "Noto Serif SC", serif; animation: ob-gold .7s 2.95s cubic-bezier(.3,1.6,.5,1) both; }
@keyframes ob-gold { 50% { transform: scale(1.18); } to { color: var(--ob-gold); } }
.ob-methods__core small { position: relative; max-width: 66%; margin-top: 3px; color: var(--ink-soft); font-size: 9.5px; font-weight: 900; line-height: 1.15; text-align: center; animation: ob-enter .4s 3.1s both; }
.ob-methods__core::after { content: ""; position: absolute; inset: -8px; border-radius: 50%; box-shadow: 0 0 0 0 var(--ob-gold); opacity: 0; animation: ob-glow 1.6s 3s ease-out both; }
@keyframes ob-glow { 0% { opacity: .7; box-shadow: 0 0 0 0 var(--ob-gold); } 100% { opacity: 0; box-shadow: 0 0 0 18px var(--ob-gold); } }
.ob-method { position: absolute; display: flex; align-items: center; gap: 7px; padding: 5px 11px 5px 5px; border: 1.5px solid var(--c); border-radius: 15px; background: var(--t); color: var(--ink); font-size: 12.5px; font-weight: 800; white-space: nowrap; translate: -50% -50%; animation: ob-part .5s calc(.3s + var(--i) * .55s) cubic-bezier(.3,1.5,.5,1) both; }
.ob-method b { display: grid; place-items: center; width: 28px; height: 28px; border-radius: 9px; background: var(--c); color: var(--white); font: 700 17px/1 "Noto Serif SC", serif; }
.ob-method:nth-of-type(1) { left: 20.7%; top: 20%; }
.ob-method:nth-of-type(2) { left: 79.3%; top: 20%; }
.ob-method:nth-of-type(3) { left: 20.7%; top: 80%; }
.ob-method:nth-of-type(4) { left: 79.3%; top: 80%; }

/* The garden, as on the Garden tab: characters light up to their state, mastered ones in gold. */
.ob-garden { padding: 12px 12px 13px; border: 1px solid var(--line); border-radius: 22px; background: rgba(var(--glass-rgb), .82); box-shadow: 0 16px 34px -24px rgba(41,73,59,.6); text-align: left; }
.ob-garden__bar { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; padding: 0 2px; }
.ob-garden__bar > b { font-size: 16px; font-weight: 900; letter-spacing: -.02em; }
.ob-garden__bar span { color: var(--ink-soft); font-size: 12px; font-weight: 800; }
.ob-garden__count { color: var(--ob-gold); font-size: 17px; font-variant-numeric: tabular-nums; }
.ob-garden__chips { display: flex; gap: 5px; margin: 8px 0 10px; }
.ob-garden__chips span { padding: 4px 9px; border: 1px solid var(--line); border-radius: 99px; color: var(--ink-soft); font-size: 10.5px; font-weight: 800; }
.ob-garden__chips .is-selected { border-color: var(--ink); background: var(--ink); color: var(--on-ink); }
.ob-garden__grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; }
.ob-garden .character-tile { border-radius: 12px; cursor: default; animation: ob-tile .5s var(--d) cubic-bezier(.3,1.4,.5,1) both; }
.ob-garden .character-tile.state-new { animation: none; }
.ob-garden .character-tile.shine--burst { animation: ob-tile-gold .65s var(--d) cubic-bezier(.3,1.5,.5,1) both; }
.ob-garden .character-tile__hanzi { font-size: 21px; }
.ob-garden .character-tile__meta { font-size: 8.5px; }
@keyframes ob-tile { from { opacity: .5; filter: grayscale(1); transform: scale(.88); } }
@keyframes ob-tile-gold { 0% { opacity: .5; filter: grayscale(1); transform: scale(.88); } 60% { opacity: 1; filter: none; transform: scale(1.14) rotate(-3deg); } 100% { transform: none; } }

/* A passed mock test: the score fills its ring, each section its bar. */
.ob-exam { padding: 14px 14px 12px; border: 1px solid var(--line); border-radius: 22px; background: rgba(var(--glass-rgb), .86); box-shadow: 0 16px 34px -24px rgba(41,73,59,.6); text-align: left; }
.ob-exam__head { display: flex; align-items: center; gap: 10px; }
.ob-exam__seal { display: grid; flex: none; place-items: center; width: 38px; height: 38px; border-radius: 12px 12px 12px 4px; background: var(--red); color: var(--on-red); font: 700 21px/1 "Noto Serif SC", serif; transform: rotate(-4deg); }
.ob-exam__head b { display: block; font-size: 16px; font-weight: 900; letter-spacing: -.02em; }
.ob-exam__head small { color: var(--ink-soft); font-size: 11.5px; font-weight: 700; }
.ob-exam__body { display: grid; grid-template-columns: 104px 1fr; align-items: center; gap: 16px; margin-top: 14px; }
.ob-exam__score { position: relative; display: grid; place-items: center; width: 104px; aspect-ratio: 1; margin-bottom: 8px; }
.ob-exam__score svg { position: absolute; inset: 0; width: 100%; height: 100%; rotate: -90deg; }
.ob-exam__score circle { fill: none; stroke: var(--paper-deep); stroke-width: 9; }
.ob-exam__score .ob-exam__fill { stroke: var(--green); stroke-linecap: round; animation: ob-arc 1.1s .45s cubic-bezier(.3,.7,.3,1) both; }
.ob-exam__score > b { font-size: 27px; font-weight: 900; letter-spacing: -.04em; font-variant-numeric: tabular-nums; }
.ob-exam__score em { position: absolute; bottom: -9px; padding: 3px 9px; border-radius: 99px; background: var(--green); color: var(--white); font-size: 11px; font-style: normal; font-weight: 900; white-space: nowrap; animation: ob-pop .45s 1.55s cubic-bezier(.3,1.6,.5,1) both; }
.ob-exam__sections { display: grid; gap: 11px; }
.ob-exam__section span { display: flex; justify-content: space-between; gap: 6px; margin-bottom: 5px; font-size: 12.5px; font-weight: 800; }
.ob-exam__section span b { color: var(--green-ink); }
.ob-exam__section i { position: relative; display: block; height: 8px; border-radius: 8px; background: var(--paper-deep); }
.ob-exam__section i::before { content: ""; position: absolute; inset: 0 auto 0 0; width: var(--p); border-radius: inherit; background: var(--green); transform-origin: left; animation: ob-fill .9s calc(.6s + var(--i) * .2s) cubic-bezier(.3,.7,.3,1) both; }
.ob-exam__section i::after { content: ""; position: absolute; top: -3px; bottom: -3px; left: var(--pass); width: 2px; border-radius: 2px; background: var(--ink); opacity: .45; }
.ob-exam__pass { color: var(--ink-soft); font-size: 10.5px; font-weight: 700; }
.ob-exam__pass::before { content: ""; display: inline-block; width: 2px; height: 9px; margin-right: 6px; border-radius: 2px; background: var(--ink); opacity: .45; vertical-align: -1px; }

@media (prefers-reduced-motion: reduce) {
  .onboarding__body.is-entering > *, .onboarding__body.is-entering .mascot, #onboardingProgress span.is-current::after,
  .ob-hello, .ob-tea, .onboarding__demo b, .onboarding__demo small, .ob-speak, .ob-speak::before, .ob-wave,
  .pace-chart__line, .pace-chart__dot, .pace-chart__end, .pace-chart__badge, .ob-pace__mascot .mascot, .ob-pace__line,
  .ob-year__grid i, .ob-year__pin,
  .ob-write__stroke, .ob-part, .ob-quiz *, .ob-methods *, .ob-methods__core::after, .ob-garden .character-tile, .ob-exam * { animation: none !important; }
  .ob-methods__glyph { color: var(--ob-gold); }
  .ob-steam, .ob-tea-steam, .ob-spark, .ob-confetti { display: none; }
}

@media (max-height: 700px) {
  .daily-word { display: none; }
  .onboarding__mascot { width: 150px; height: 150px; }
  .onboarding__body h1 { font-size: 27px; }
  .onboarding__mascot.pace-chart { width: min(300px, 84vw); }
  .onboarding__stage[data-scene="year"] .onboarding__mascot { width: 86px; height: 86px; }
  .ob-pace__mascot { width: 52px; height: 52px; }
  .ob-write__box { width: min(170px, 27dvh); }
  .ob-quiz__prompt span { font-size: 50px; }
  .ob-quiz .probe-option { min-height: 42px; }
  .ob-garden .character-tile__meta { display: none; }
  .ob-methods { width: min(290px, 100%); }
}

/* Touch handwriting practice. */
#playModeControl { grid-template-columns: repeat(3, 1fr); }
.handwriting {
  position: absolute; z-index: 6; inset: 0; display: flex; min-height: 0;
  flex-direction: column; align-items: center; overflow-y: auto; padding: 14px 14px 10px;
  border-radius: 30px 30px 68px 30px; background: var(--white); box-shadow: var(--shadow);
  overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
}
.handwriting__eyebrow { margin: 0; color: var(--red-dark); font-size: 9px; font-weight: 800; letter-spacing: .16em; }
.handwriting__word { display: flex; min-height: 38px; align-items: center; justify-content: center; gap: 6px; margin-top: 4px; }
.handwriting__word span { color: var(--ink-soft); font: 25px "Noto Serif SC", serif; opacity: .38; }
.handwriting__word span.is-active { color: var(--ink); opacity: 1; transform: scale(1.14); }
.handwriting__word span.is-done { color: var(--green); opacity: 1; }
.handwriting__meaning { margin: 1px 0 2px; color: var(--ink-soft); font-size: 11px; font-weight: 700; text-align: center; }
.handwriting__reference { min-height: 28px; margin: 0; color: var(--ink); font: 25px "Noto Serif SC", serif; }
.handwriting__canvas {
  position: relative; width: min(270px, calc(100vw - 64px)); height: min(270px, calc(100vw - 64px)); flex: 0 0 auto;
  border: 1px solid var(--line); border-radius: 18px; background-color: var(--white);
  background-image: linear-gradient(rgba(23,59,54,.08) 1px, transparent 1px), linear-gradient(90deg, rgba(23,59,54,.08) 1px, transparent 1px);
  background-size: 50% 50%; overflow: hidden; touch-action: none;
}
.handwriting__canvas svg, .handwriting__canvas canvas { display: block; touch-action: none; }
.handwriting__writer-svg > g > path { filter: url(#handwritingLiveBrush); }
.handwriting__writer-svg.is-concealed { visibility: hidden; }
.handwriting__brush-overlay { position: absolute; z-index: 2; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.handwriting__brush-stroke { fill: #df553f; filter: drop-shadow(0 .4px .35px rgba(80, 35, 22, .2)); }
.handwriting__comparison { position: absolute; inset: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--line); }
.handwriting__comparison-side { position: relative; display: flex; min-width: 0; flex-direction: column; align-items: center; justify-content: center; background: var(--white); }
/* Both captions share one baseline at the foot of the card. */
.handwriting__comparison-side small { position: absolute; right: 0; bottom: 9px; left: 0; color: var(--ink-soft); font-size: 10px; font-weight: 700; opacity: .75; text-align: center; }
.handwriting__comparison-reference span { color: #173b36; font: clamp(72px, 24vw, 102px) "Noto Serif SC", serif; line-height: 1; }
.handwriting__comparison-drawing { padding: 4px; }
.handwriting__result-svg { width: 100%; height: auto; max-height: calc(100% - 24px); }
/* The verdict takes the prompt's place once the glyph is written. */
.handwriting__eyebrow[data-verdict] { position: relative; color: var(--ink-soft); font-size: 17px; font-weight: 900; letter-spacing: .02em; line-height: 1.2; animation: verdict-in .45s cubic-bezier(.2,1.5,.4,1) both; }
.handwriting__eyebrow[data-verdict="good"] { color: var(--green); }
/* Perfect: gold ink with a light sweeping across it and a warm halo; two
 * sparks twinkle at the sides and the card glows. A cousin of the legendary
 * sticker (glow + shine), without its rays and violet. */
.handwriting__eyebrow[data-verdict="perfect"] { padding: 0 20px; }
.handwriting__eyebrow[data-verdict="perfect"] .handwriting__verdict {
  background: linear-gradient(100deg, #b8741a 0%, #eaa92a 32%, #fff1bf 47%, #eaa92a 62%, #c9661c 100%);
  background-size: 260% 100%; -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 0 8px rgba(245, 180, 50, .65));
  animation: verdict-shine 2.8s ease-in-out .4s infinite;
}
.handwriting__eyebrow[data-verdict="perfect"]::before, .handwriting__eyebrow[data-verdict="perfect"]::after {
  content: "✦"; position: absolute; top: 50%; color: #f2b632; font-size: 11px; translate: 0 -50%;
  text-shadow: 0 0 6px rgba(245, 180, 50, .8); animation: verdict-spark 1.8s ease-in-out infinite;
}
.handwriting__eyebrow[data-verdict="perfect"]::before { left: 0; }
.handwriting__eyebrow[data-verdict="perfect"]::after { right: 0; font-size: 8px; animation-delay: .9s; }
.handwriting__canvas.is-perfect { border-color: rgba(234, 169, 42, .6); box-shadow: 0 0 0 1px rgba(234, 169, 42, .3), 0 0 20px rgba(245, 180, 50, .3); animation: perfect-glow 2.8s ease-in-out infinite; }
@keyframes verdict-in { from { opacity: 0; scale: .6; } }
@keyframes verdict-shine { 0% { background-position: 100% 0; } 60%, 100% { background-position: 0 0; } }
@keyframes verdict-spark { 50% { opacity: .35; scale: .7; } }
@keyframes perfect-glow { 0%, 100% { box-shadow: 0 0 0 1px rgba(234, 169, 42, .25), 0 0 16px rgba(245, 180, 50, .22); } 50% { box-shadow: 0 0 0 1px rgba(234, 169, 42, .45), 0 0 26px rgba(245, 180, 50, .42); } }
@media (prefers-reduced-motion: reduce) {
  .handwriting__eyebrow[data-verdict], .handwriting__eyebrow[data-verdict] .handwriting__verdict, .handwriting__eyebrow[data-verdict]::before, .handwriting__eyebrow[data-verdict]::after { animation: none; }
  .handwriting__eyebrow[data-verdict="perfect"] .handwriting__verdict { background-position: 50% 0; }
  .handwriting__canvas.is-perfect { animation: none; }
}
.handwriting__status { min-height: 18px; margin: 6px 0 4px; color: var(--ink-soft); font-size: 11px; font-weight: 700; }
.handwriting__tools, .handwriting__complete { display: grid; width: 100%; grid-template-columns: 1fr 1fr; gap: 8px; }
.handwriting__tools button { min-height: 40px; padding: 7px 9px; border: 1px solid var(--line); border-radius: 13px; background: var(--paper); color: var(--ink); font-size: 10px; font-weight: 800; }
.handwriting__complete .menu-primary, .handwriting__complete .menu-secondary { min-height: 44px; margin: 0; justify-content: center; }
.handwriting-auto-hint { margin-top: 12px; text-align: left; }
.handwriting-auto-hint > span:first-child { display: grid; gap: 2px; }
.handwriting-auto-hint b { font-size: 11px; }
.handwriting-auto-hint small { color: var(--ink-soft); font-size: 9px; line-height: 1.35; }
@media (max-height: 690px) {
  .handwriting { padding-top: 8px; }
  .handwriting__canvas { width: min(220px, calc(100vw - 84px)); height: min(220px, calc(100vw - 84px)); }
  .handwriting__reference { min-height: 23px; font-size: 21px; }
}

/* ==================================================================
 * Roadmap: levels, path, achievements, cloze, exam, tutorials, paywall
 * ================================================================== */

.pro-badge { display: inline-block; margin-left: 5px; padding: 1px 6px; border-radius: 99px; background: var(--ink); color: var(--paper); font-size: 8px; font-style: normal; font-weight: 800; letter-spacing: .08em; vertical-align: middle; }
.segmented button .pro-badge { display: block; width: max-content; margin: 3px auto 0; }
.fieldset-hint { margin: -2px 2px 10px; color: var(--ink-soft); font-size: 11px; line-height: 1.4; }

/*
 * Bao's line (home): the bubble opens from Bao's side, and Bao slides left to
 * make room. The wrapper animates its width; the bubble keeps a fixed width
 * inside it so the text never re-wraps mid-animation.
 */
.hero-bao { display: flex; justify-content: center; align-items: center; container-type: inline-size; }
.bao-say { flex: none; max-width: 0; overflow: hidden; opacity: 0; transition: max-width .45s cubic-bezier(.2,.75,.25,1), opacity .3s ease; }
.bao-say.is-open { max-width: 244px; opacity: 1; }
.bao-bubble { position: relative; display: block; width: 200px; width: min(222px, calc(100cqw - 128px)); margin: 6px 4px 14px 16px; padding: 9px 12px; border: 1px solid var(--line); border-radius: 16px; background: var(--white); color: var(--ink); font-size: 12.5px; font-weight: 650; line-height: 1.38; text-align: left; overflow-wrap: anywhere; box-shadow: 0 10px 24px -16px rgba(41,73,59,.45); cursor: pointer; }
.bao-bubble::before { content: ""; position: absolute; top: 50%; left: -6px; width: 10px; height: 10px; border-bottom: 1px solid var(--line); border-left: 1px solid var(--line); background: inherit; transform: translateY(-50%) rotate(45deg); }
.bao-bubble.has-cta::after { content: "›"; margin-left: 5px; color: var(--red); font-weight: 800; }
@media (prefers-reduced-motion: reduce) { .bao-say { transition: none; } }

/* --- hero level chip (home), next to the streak --- */
.hero-chips { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 6px; margin: 0 0 8px; }
.hero-chips .streak-chip { margin: 0; }
/* The pill fills from the left with progress towards the next level. */
.level-chip { position: relative; isolation: isolate; display: inline-flex; align-items: center; gap: 5px; overflow: hidden; padding: 4px 11px; border: 1px solid var(--line); border-radius: 999px; background: rgba(var(--glass-rgb), .66); color: var(--ink); font-size: 11px; white-space: nowrap; cursor: pointer; }
.level-chip::before { content: ""; position: absolute; inset: 0; z-index: -1; background: linear-gradient(90deg, rgba(239,184,142,.45), rgba(223,85,63,.28)); transform-origin: left; transform: scaleX(var(--xp, 0)); transition: transform .5s cubic-bezier(.2,.75,.25,1); }
.level-chip b { font-weight: 800; }
.level-chip span { color: var(--red-dark); font-weight: 800; }

/* --- stacked progress (home): mastered, remembered, learning --- */
.stack-bar { display: flex; height: 9px; overflow: hidden; border-radius: 99px; background: rgba(23,59,54,.11); }
.stack-bar__seg { height: 100%; width: 0; transition: width .5s cubic-bezier(.2,.75,.25,1); }
.stack-bar__seg + .stack-bar__seg { box-shadow: inset 1px 0 0 rgba(var(--glass-rgb), .8); }
.stack-bar__seg--mastered, .stack-legend__item--mastered i { background: var(--stack-mastered); }
.stack-bar__seg--remembered, .stack-legend__item--remembered i { background: var(--stack-remembered); }
.stack-bar__seg--learning, .stack-legend__item--learning i { background: var(--stack-learning); }
.stack-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; margin-top: 8px; color: var(--ink-soft); font-size: 11px; font-weight: 700; }
.stack-legend__item { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.stack-legend__item i { width: 8px; height: 8px; border-radius: 50%; }
.stack-legend__item b { color: var(--ink); font-weight: 800; }
.stack-legend__total { margin-left: auto; }
:root[data-theme="dark"] .stack-bar,
:root[data-theme="dark"] .progress-track { background: rgba(229,235,217,.12); }

/* A soft glow behind Bao that changes with the level stage. */
.mascot-slot[data-stage] { position: relative; }
.mascot-slot[data-stage]::before { content: ""; position: absolute; inset: 6%; z-index: -1; border-radius: 50%; background: radial-gradient(circle, var(--stage-glow, transparent) 0 58%, transparent 70%); }
.mascot-slot[data-stage="dough"] { --stage-color: #c9bca6; --stage-glow: rgba(201,188,166,.18); }
.mascot-slot[data-stage="filling"] { --stage-color: #b8a07c; --stage-glow: rgba(184,160,124,.2); }
.mascot-slot[data-stage="folded"] { --stage-color: #8fb096; --stage-glow: rgba(143,176,150,.24); }
.mascot-slot[data-stage="steaming"] { --stage-color: #6f9fae; --stage-glow: rgba(111,159,174,.24); }
.mascot-slot[data-stage="fluffy"] { --stage-color: #a58bc4; --stage-glow: rgba(165,139,196,.24); }
.mascot-slot[data-stage="golden"] { --stage-color: #d9a441; --stage-glow: rgba(217,164,65,.28); }
.mascot-slot[data-stage="master"] { --stage-color: #df553f; --stage-glow: rgba(223,85,63,.24); }

/* --- path card (home) --- */
.path-card { display: block; width: 100%; margin-bottom: 8px; padding: 14px; border: 1px solid var(--line); border-radius: 20px; background: var(--white); color: var(--ink); font: inherit; text-align: left; box-shadow: 0 8px 28px -22px rgba(41,73,59,.28); cursor: pointer; }
.path-card .menu-kicker, .daily-word .menu-kicker { display: block; color: var(--red-dark); }
.path-card__row { display: flex; align-items: center; gap: 12px; margin: 8px 0 10px; }
.path-card__glyph { display: grid; width: 48px; height: 48px; flex: 0 0 auto; place-items: center; border-radius: 16px 16px 16px 6px; background: var(--ink); color: var(--paper); font: 26px "Noto Serif SC", serif; }
.path-card__copy { display: flex; min-width: 0; flex: 1; flex-direction: column; }
.path-card__copy b { font-size: 16px; font-weight: 800; letter-spacing: -.02em; }
.path-card__copy small { margin-top: 3px; color: var(--ink-soft); font-size: 11px; font-weight: 700; }
/* The whole chapter; the tick marks where its checkpoint opens. */
.path-card__track { position: relative; display: block; overflow: visible; }
.path-card__track > span { overflow: hidden; }
.path-card__mark { position: absolute; top: -3px; bottom: -3px; width: 2px; margin-left: -1px; border-radius: 1px; background: var(--ink); opacity: .55; }
.offer-card { cursor: default; }
.offer-card h2 { margin: 6px 0 0; font-size: 16px; }
.offer-card p { margin: 3px 0 0; color: var(--ink-soft); font-size: 11px; font-weight: 700; }
.offer-card__actions { display: flex; align-items: center; gap: 14px; margin-top: 10px; }
.offer-card__actions .menu-secondary { flex: 1; margin: 0; }

/* --- path screen --- */
.path-screen, .achievements-screen { display: flex; flex-direction: column; padding: max(16px, env(safe-area-inset-top)) 16px 0; }
.path-heading { flex: 1; min-width: 0; text-align: center; }
.path-heading h2 { margin: 0; font-size: 19px; }
.path-heading small { color: var(--ink-soft); font-size: 10px; font-weight: 700; }
.header-spacer { width: 44px; }
.path-scroll, .achievements-scroll { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 8px 4px 24px; }
/* Chapters scrolled past the edges fade out instead of being sliced off. */
.path-scroll { -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 14px, #000 calc(100% - 14px), transparent 100%); mask-image: linear-gradient(to bottom, transparent 0, #000 14px, #000 calc(100% - 14px), transparent 100%); }
.path-level { margin: 6px 0 2px; color: var(--ink-soft); font-size: 10px; font-weight: 800; letter-spacing: .16em; text-align: center; }
.path-map { position: relative; margin: 0; padding: 30px 0 8px; list-style: none; }
.path-node { position: relative; height: 92px; }
.path-trail { position: absolute; top: 0; left: 0; z-index: 0; overflow: visible; pointer-events: none; }
.path-trail path { fill: none; stroke-linecap: round; stroke-width: 3; }
.path-trail__base { stroke: var(--line); stroke-dasharray: 7 7; }
.path-trail__done { stroke: var(--red); stroke-dasharray: 7 7; opacity: .6; }
.path-node__button { position: absolute; top: 14px; left: calc(50% - 32px + var(--offset, 0px)); z-index: 1; width: 64px; height: 64px; padding: 0; border: 0; background: transparent; color: var(--ink); cursor: pointer; }
.path-node__disc { position: relative; display: grid; width: 64px; height: 64px; place-items: center; border: 3px solid var(--line); border-radius: 50%; background: var(--white); font: 28px "Noto Serif SC", serif; box-shadow: 0 8px 18px -12px rgba(23,59,54,.5); }
/* Only the progress ring: Bao (also an SVG in the disc) must not turn or restyle. */
.path-node__ring { position: absolute; inset: -3px; width: calc(100% + 6px); height: calc(100% + 6px); transform: rotate(-90deg); }
.path-node__ring circle { fill: none; stroke: var(--red); stroke-width: 3; stroke-linecap: round; }
.path-node__label { position: absolute; top: 50%; left: 76px; display: grid; width: 118px; gap: 1px; text-align: left; transform: translateY(-50%); }
.path-node.is-right .path-node__label { right: 76px; left: auto; text-align: right; }
.path-node__label b { font-size: 12px; line-height: 1.2; }
.path-node__label small { color: var(--ink-soft); font-size: 9px; font-weight: 700; }
.path-node.is-done .path-node__disc { border-color: var(--red); background: var(--tint-red); }
.path-node.is-current .path-node__disc { border-color: var(--ink); background: var(--ink); color: var(--paper); transform: scale(1.08); }
/* The current chapter is ready for its checkpoint: a gold ring invites the test. */
.path-node.is-ready .path-node__disc { box-shadow: 0 0 0 3px #e3b341, 0 0 18px rgba(227, 179, 65, .55); }
.path-node.is-locked .path-node__disc { border-color: var(--paper-deep); background: var(--paper); color: rgba(75,98,93,.5); box-shadow: none; }
.path-node.is-locked .path-node__label { opacity: .6; }
.path-node__bao { position: absolute; bottom: -8px; left: -30px; z-index: 2; width: 44px; height: 44px; pointer-events: none; }
.path-node.is-right .path-node__bao { right: -30px; left: auto; }
.path-node__bao .mascot { width: 100%; height: 100%; }
.path-node__crown { position: absolute; top: -9px; right: -6px; font-size: 16px; }
.path-hint { margin: 8px 16px 0; color: var(--ink-soft); font-size: 11px; line-height: 1.45; text-align: center; }

/* --- chapter sheet --- */
.chapter-card { text-align: center; }
.chapter-card__glyph { display: grid; width: 64px; height: 64px; margin: 0 auto 8px; place-items: center; border-radius: 20px 20px 20px 8px; background: var(--ink); color: var(--paper); font: 34px "Noto Serif SC", serif; }
.chapter-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin: 10px 0 12px; }
.chapter-stats div { padding: 9px 4px; border-radius: 14px; background: var(--paper); }
.chapter-stats b { display: block; font-size: 20px; }
.chapter-stats small { color: var(--ink-soft); font-size: 9px; font-weight: 700; }
/* Three whole rows; when more wait below, the last row fades to say it scrolls. */
.chapter-words { display: flex; max-height: 80px; flex-wrap: wrap; justify-content: center; gap: 4px 7px; margin: 0 0 14px; overflow-y: auto; font: 17px/24px "Noto Serif SC", serif; }
.chapter-words.is-clipped { mask-image: linear-gradient(#000 60%, transparent); -webkit-mask-image: linear-gradient(#000 60%, transparent); }
.chapter-words span { color: var(--ink-soft); opacity: .5; }
.chapter-words span.is-seen { color: var(--ink); opacity: .85; }
.chapter-words span.is-mastered { color: var(--red-dark); opacity: 1; }
.chapter-card .menu-secondary { margin-top: 8px; }

/* --- achievements --- */
.achievements-card { display: flex; width: 100%; align-items: center; gap: 12px; margin-top: 10px; padding: 14px 16px; border: 1px solid var(--line); border-radius: 20px; background: var(--white); color: var(--ink); text-align: left; cursor: pointer; }
.achievements-card__icons { display: flex; flex-shrink: 0; }
.achievements-card__icons img { width: 40px; height: 40px; object-fit: contain; filter: drop-shadow(0 2px 3px rgba(37,45,34,.18)); }
.achievements-card__icons img + img { margin-left: -10px; }
.achievements-card__icons img.is-locked { filter: grayscale(1); opacity: .45; }
.achievements-card__copy { display: grid; flex: 1; min-width: 0; }
.achievements-card__copy b { font-size: 14px; }
.achievements-card__copy small { color: var(--ink-soft); font-size: 10px; font-weight: 700; }
.achievement-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; margin: 0; padding: 0; list-style: none; }
.achievement { display: grid; justify-items: center; gap: 4px; padding: 14px 10px 12px; border: 1px solid var(--line); border-radius: 18px; background: var(--white); text-align: center; }
.achievement__badge { position: relative; display: block; width: 96px; height: 80px; margin-bottom: 2px; }
.achievement__art { --pad: 16px; position: absolute; inset: calc(var(--pad) * -1); display: block; box-sizing: border-box; padding: var(--pad); filter: grayscale(1); opacity: .38; }
.achievement.is-unlocked .achievement__art { filter: drop-shadow(0 5px 8px rgba(37,45,34,.16)); opacity: 1; transform-origin: 50% 90%; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.achievement__art.is-hopping { animation: sticker-hop .6s ease-out; }
@media (prefers-reduced-motion: reduce) { .achievement__art.is-hopping { animation: none; } }

/* --- achievement tiers (achievements.js → TIERS), hardest first --- */
.achievement[data-tier="legendary"], .achievement-tier[data-tier="legendary"] { --tier-bg: linear-gradient(90deg, #7b4dff, #ff4f9a); --tier-ink: #fff; }
.achievement[data-tier="gold"], .achievement-tier[data-tier="gold"] { --tier-bg: #f4c64f; --tier-ink: #4c2a05; }
.achievement[data-tier="silver"], .achievement-tier[data-tier="silver"] { --tier-bg: #dde2e8; --tier-ink: #3b4652; }
.achievement[data-tier="bronze"], .achievement-tier[data-tier="bronze"] { --tier-bg: #ecc19b; --tier-ink: #5a2f12; }
.achievement__tier { padding: 2px 8px; border-radius: 99px; background: var(--tier-bg); color: var(--tier-ink); font-size: 8.5px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; }
.achievement:not(.is-unlocked) .achievement__tier { opacity: .55; }
.achievement-tier { display: flex; grid-column: 1 / -1; align-items: center; gap: 8px; margin: 12px 2px 0; }
.achievement-tier:first-child { margin-top: 0; }
.achievement-tier::before { width: 12px; height: 12px; flex: 0 0 auto; border-radius: 50%; background: var(--tier-bg); content: ""; }
.achievement-tier::after { height: 1px; flex: 1; background: var(--line); content: ""; }
.achievement-tier b { font-size: 12px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
.achievement-tier small { color: var(--ink-soft); font-size: 11px; font-weight: 800; }

/*
 * Legendary: the badge reveal. Gold rays turn behind the sticker over a
 * violet glow, a light sweeps across the sticker's own shape (a white copy
 * masked by a moving band), sparkles twinkle. In the unlock modal a ring
 * bursts and confetti flies first.
 */
.achievement-grid .achievement.is-unlocked[data-tier="legendary"] { overflow: hidden; border-color: rgba(139,92,255,.38); background: linear-gradient(165deg, rgba(139,92,255,.13), rgba(255,79,154,.08) 55%, var(--white)); }
.legend-glow, .legend-rays { position: absolute; top: 50%; left: 50%; aspect-ratio: 1; border-radius: 50%; translate: -50% -50%; pointer-events: none; }
.legend-glow { width: 150%; background: radial-gradient(circle, rgba(161,92,255,.5), rgba(255,79,154,.2) 45%, transparent 68%); animation: legend-pulse 2.8s ease-in-out infinite; }
.legend-rays { width: 200%; background: repeating-conic-gradient(rgba(255,196,70,.6) 0 4deg, transparent 4deg 22.5deg); -webkit-mask-image: radial-gradient(circle, transparent 20%, #000 32%, transparent 68%); mask-image: radial-gradient(circle, transparent 20%, #000 32%, transparent 68%); animation: legend-spin 18s linear infinite; }
.legend-shine { position: absolute; top: var(--pad, 0px); left: var(--pad, 0px); width: calc(100% - 2 * var(--pad, 0px)); height: calc(100% - 2 * var(--pad, 0px)); object-fit: contain; filter: brightness(0) invert(1); opacity: .75; pointer-events: none; -webkit-mask-image: linear-gradient(110deg, transparent 38%, #000 50%, transparent 62%); mask-image: linear-gradient(110deg, transparent 38%, #000 50%, transparent 62%); -webkit-mask-size: 300% 100%; mask-size: 300% 100%; -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat; animation: legend-shine 3.6s ease-in-out 1.2s infinite both; }
.achievement__badge .sticker-spark { z-index: 1; }
.sticker-stack.is-legendary .legend-glow { width: 230px; animation: legend-in .6s .45s both, legend-pulse 2.8s ease-in-out 1.05s infinite; }
.sticker-stack.is-legendary .legend-rays { width: 300px; animation: legend-in .6s .45s both, legend-spin 18s linear infinite; }
/* The card's text stays above the rays. */
.sticker-stack.is-legendary ~ * { position: relative; }
.legend-ring { position: absolute; top: 50%; left: 50%; width: 120px; aspect-ratio: 1; border: 3px solid #ffc93c; border-radius: 50%; box-shadow: 0 0 18px rgba(255,201,60,.7); opacity: 0; translate: -50% -50%; pointer-events: none; animation: legend-ring .9s ease-out .45s forwards; }
.legend-confetti { position: absolute; top: 50%; left: 50%; width: 6px; height: 11px; margin: -5px 0 0 -3px; border-radius: 2px; background: var(--c); opacity: 0; pointer-events: none; animation: legend-confetti 1.4s cubic-bezier(.15,.7,.3,1) .5s forwards; }
@keyframes legend-spin { to { rotate: 360deg; } }
@keyframes legend-pulse { 50% { opacity: .75; scale: 1.08; } }
@keyframes legend-in { from { opacity: 0; scale: .3; } }
@keyframes legend-shine { 0%, 55% { -webkit-mask-position: 100% 0; mask-position: 100% 0; } 100% { -webkit-mask-position: 0 0; mask-position: 0 0; } }
@keyframes legend-ring { 0% { opacity: .95; scale: .3; } 100% { opacity: 0; scale: 2.3; } }
@keyframes legend-confetti {
  0% { opacity: 1; transform: rotate(var(--a)) translateY(0) scale(.5); }
  75% { opacity: 1; }
  100% { opacity: 0; transform: rotate(var(--a)) translateY(calc(var(--d) * -1)) rotate(var(--r)); }
}
@media (prefers-reduced-motion: reduce) {
  .legend-glow, .legend-rays, .legend-shine, .sticker-stack.is-legendary .legend-glow, .sticker-stack.is-legendary .legend-rays { animation: none; }
  .legend-shine, .legend-ring, .legend-confetti { display: none; }
}
.achievement b { font-size: 12px; line-height: 1.2; }
.achievement small { color: var(--ink-soft); font-size: 9.5px; line-height: 1.35; }
.achievement .progress-track { width: 80%; height: 5px; margin-top: 2px; }
.achievement__meta { color: var(--ink-soft); font-size: 9px; font-weight: 800; }
.achievement.is-unlocked .achievement__meta { color: var(--red-dark); }

/* --- session: reason line, cloze, exam --- */
.probe__reason { align-self: center; margin: 0 0 -4px; padding: 3px 10px; border-radius: 99px; background: rgba(23,59,54,.07); color: var(--ink-soft); font-size: 10px; font-weight: 800; letter-spacing: .04em; text-align: center; }
.quiz-hanzi.quiz-prompt--phrase { font-family: "Noto Serif SC", serif; font-size: clamp(26px, 8vw, 36px); line-height: 1.35; letter-spacing: .02em; text-align: center; }
.quiz-hanzi .cloze-gap { display: inline-block; margin: 0 .08em; color: var(--red); letter-spacing: -.1em; }
.probe__question.is-hint { color: var(--ink-soft); font-size: 14px; font-style: italic; text-align: center; }
.cloze-full { margin: 0; font: 24px "Noto Serif SC", serif; text-align: center; }
.cloze-full b { color: var(--red-dark); }
.cloze-ru { margin: 0 0 6px; color: var(--ink-soft); font-size: 13px; text-align: center; }
.probe-option.is-picked { border-color: var(--ink); background: var(--paper-deep); box-shadow: inset 0 0 0 1px var(--ink); }
.result-sub { margin: 6px 0 0; color: var(--ink-soft); font-size: 13px; font-weight: 700; }
/* Bao reacts to the round once it is over (never during it). */
.result-bao { display: flex; align-items: center; gap: 12px; margin-top: 14px; }
.result-bao[hidden] { display: none; }
.result-bao__mascot { flex: none; width: 84px; height: 84px; }
.result-bao__mascot .mascot { animation: result-bao-hop .7s ease-out both; transform-origin: 50% 90%; }
.result-bao__line { margin: 0; padding: 12px 15px; border: 1px solid var(--line); border-radius: 18px 18px 18px 6px; background: var(--white); color: var(--ink); font-size: 14px; font-weight: 700; line-height: 1.4; animation: result-bao-line .4s .2s ease-out both; }
@keyframes result-bao-hop { 0% { opacity: 0; transform: translateY(14px) scale(.85) } 55% { opacity: 1; transform: translateY(-8px) scale(1.04) } 100% { transform: none } }
@keyframes result-bao-line { from { opacity: 0; transform: translateX(-8px) } }
.result-screen.is-exam-passed .result-heading h1 { color: var(--hit); }
.result-screen.is-exam-failed .result-heading h1 { color: var(--red-dark); }

/* --- tutorials --- */
.tutorial { position: absolute; z-index: 45; inset: 0; display: flex; flex-direction: column; padding-top: max(18px, env(safe-area-inset-top)); background: var(--paper); }
.tutorial__body { display: flex; flex: 1; min-height: 0; flex-direction: column; align-items: center; justify-content: center; overflow-y: auto; padding: 10px 26px; text-align: center; }
.tutorial__mascot { width: min(150px, 40vw); height: min(150px, 20dvh); margin-bottom: 6px; }
.tutorial__body h1 { max-width: 340px; margin: 10px 0 8px; font-size: 28px; line-height: 1.12; letter-spacing: -.04em; }
.tutorial__body > p { max-width: 330px; margin: 0; color: var(--ink-soft); font-size: 14px; line-height: 1.55; }
.tutorial__demo { width: min(320px, 100%); margin-top: 18px; padding: 16px; border: 1px solid var(--line); border-radius: 22px; background: var(--white); }
.tutorial__prompt { margin: 0 0 4px; font: 40px "Noto Serif SC", serif; line-height: 1.2; }
.tutorial__prompt.is-phrase { font-size: 30px; }
.tutorial__hint { margin: 0 0 10px; color: var(--ink-soft); font-size: 13px; font-style: italic; }
.tutorial__options { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.tutorial__options .probe-option { min-height: 46px; }
.tutorial__options.is-hanzi .probe-option { font: 24px "Noto Serif SC", serif; }
.tutorial__write { width: 200px; height: 200px; margin: 0 auto; border: 1px solid var(--line); border-radius: 16px; background: var(--white); background-image: linear-gradient(rgba(23,59,54,.08) 1px, transparent 1px), linear-gradient(90deg, rgba(23,59,54,.08) 1px, transparent 1px); background-size: 50% 50%; touch-action: none; }
.tutorial__feedback { min-height: 18px; margin: 10px 0 0; font-size: 12px; font-weight: 800; color: var(--ink-soft); }
.tutorial__feedback.is-good { color: var(--hit); }
.tutorial__feedback.is-bad { color: var(--red-dark); }
.tutorial-list { display: flex; flex-wrap: wrap; gap: 7px; }
.tutorial-list button { padding: 9px 13px; border: 1px solid var(--line); border-radius: 999px; background: var(--paper); color: var(--ink); font-size: 12px; font-weight: 800; cursor: pointer; }
.tutorial-list button.is-seen::after { content: " ✓"; color: var(--hit); }

/* --- paywall --- */
.paywall-card { max-width: 380px; padding: 20px 20px 16px; text-align: center; }
.paywall-card .mascot-slot--overlay { width: 84px; height: 84px; }
.paywall-benefits { display: grid; gap: 7px; margin: 4px 0 14px; padding: 0; list-style: none; text-align: left; }
.paywall-benefits li { position: relative; padding-left: 24px; font-size: 13px; font-weight: 700; line-height: 1.35; }
.paywall-benefits li::before { content: "✓"; position: absolute; left: 0; top: 0; display: grid; width: 17px; height: 17px; place-items: center; border-radius: 50%; background: var(--tint-green); color: var(--hit); font-size: 10px; font-weight: 800; }
.plan-picker { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 12px; }
.plan-option { position: relative; display: grid; gap: 2px; padding: 13px 8px 11px; border: 1px solid var(--line); border-radius: 16px; background: var(--paper); color: var(--ink); cursor: pointer; }
.plan-option b { font-size: 14px; }
.plan-option span { font-size: 12px; font-weight: 700; }
.plan-option small { color: var(--ink-soft); font-size: 10px; }
.plan-option.is-selected { border-color: var(--red); background: var(--tint-red); box-shadow: inset 0 0 0 1px var(--red); }
.plan-option__save { position: absolute; top: -9px; left: 50%; padding: 2px 8px; border-radius: 99px; background: var(--red); color: var(--on-red) !important; font-size: 9px !important; font-weight: 800; transform: translateX(-50%); white-space: nowrap; }
.paywall-fine { margin: 8px 0 4px; color: var(--ink-soft); font-size: 11px; line-height: 1.4; }
.paywall-free { margin: 6px 0 0; font-size: 11px; font-weight: 700; line-height: 1.4; }
.paywall-card .overlay-note { margin: 6px 0 2px; }
.checkout-card { max-width: 380px; padding: 20px 20px 16px; text-align: left; }
.checkout-card .eyebrow, .checkout-card h2, .checkout-card .paywall-fine { text-align: center; }
.checkout-lines { display: grid; gap: 0; margin: 10px 0 14px; padding: 4px 14px; border: 1px solid var(--line); border-radius: 16px; background: var(--paper); }
.checkout-lines div { display: flex; justify-content: space-between; gap: 12px; padding: 9px 0; border-top: 1px solid var(--line); font-size: 13px; line-height: 1.35; }
.checkout-lines div:first-child { border-top: 0; }
.checkout-lines dt { color: var(--ink-soft); font-weight: 600; }
.checkout-lines dd { margin: 0; font-weight: 700; text-align: right; }
.checkout-lines .checkout-total { font-size: 15px; }
.checkout-lines .checkout-total dt { color: var(--ink); font-weight: 800; }
.checkout-lines .checkout-total dd { color: var(--red); font-weight: 800; }
.checkout-field { display: grid; gap: 6px; margin: 0 0 12px; font-size: 12px; font-weight: 700; color: var(--ink-soft); }
.checkout-field input { width: 100%; min-height: 46px; padding: 0 15px; border: 1px solid var(--line); border-radius: 14px; background: rgba(var(--glass-rgb), .8); color: var(--ink); font: inherit; font-size: 15px; }
.checkout-field input:focus { outline: 2px solid rgba(223,85,63,.35); }
.checkout-agree { display: flex; align-items: flex-start; gap: 10px; margin: 0 0 14px; font-size: 12px; font-weight: 600; line-height: 1.4; cursor: pointer; }
.checkout-agree input { flex: none; width: 18px; height: 18px; margin: 0; accent-color: var(--red); }
.checkout-card .menu-primary { width: 100%; }
.checkout-agree a { color: var(--red); font-weight: 700; text-decoration: underline; text-underline-offset: 2px; }
a.settings-link { color: var(--ink); text-decoration: none; }
/* Above the welcome tour: the documents come first. */
.consent-overlay { z-index: 60; }
.consent-card { max-width: 380px; }
.consent-card .mascot-slot--overlay { width: 84px; height: 84px; margin: 0 auto; }
.consent-docs { display: grid; gap: 8px; margin: 4px 0 12px; padding: 0; list-style: none; }
.consent-check { display: flex; align-items: flex-start; gap: 12px; padding: 12px 14px; border: 1px solid var(--line); border-radius: 14px; background: var(--paper); color: var(--ink); font-size: 13px; font-weight: 600; line-height: 1.35; text-align: left; cursor: pointer; }
.consent-check:has(input:checked) { border-color: var(--red); }
.consent-check input { flex: none; width: 20px; height: 20px; margin: 0; accent-color: var(--red); }
.consent-check a { color: var(--red); font-weight: 700; text-decoration: underline; text-underline-offset: 2px; }
.consent-card .menu-primary { width: 100%; margin-top: 4px; }
.consent-card .menu-primary:disabled { opacity: .45; cursor: default; }
.settings-link .card-chevron { color: var(--ink-soft); }
/* Account: sign in, add an email, sign out, delete. */
.account-card { max-width: 380px; text-align: left; }
.account-card h2, .account-card .eyebrow, .account-card .overlay-lead { text-align: center; }
.account-card .menu-primary { width: 100%; }
.account-card .menu-primary:disabled { opacity: .45; cursor: default; }
.account-card #accountCode { letter-spacing: .3em; font-variant-numeric: tabular-nums; text-align: center; }
.account-error { margin: -4px 2px 12px; color: var(--red); font-size: 12px; font-weight: 700; line-height: 1.4; }
.account-providers { display: grid; gap: 8px; margin-top: 10px; justify-items: center; }
/* Apple drawn like Google's own button beside it (outline theme, large, pill). */
.provider-button { position: relative; display: flex; width: 100%; max-width: 400px; height: 40px; align-items: center; justify-content: center; padding: 0 40px; border: 1px solid #dadce0; border-radius: 999px; background: #fff; color: #3c4043; font: 500 14px/1 "Google Sans", Roboto, -apple-system, system-ui, Arial, sans-serif; letter-spacing: .25px; cursor: pointer; transition: background-color .15s, border-color .15s; }
.provider-button:hover { border-color: #d2e3fc; background: #f8faff; }
.provider-button:focus-visible { outline: 2px solid #4285f4; outline-offset: 1px; }
.provider-button__logo { position: absolute; left: 13px; width: 15px; height: 18px; fill: #000; }
#accountGoogle { width: 100%; max-width: 400px; }
.account-danger { color: var(--red); }
.checkout-card .menu-primary:disabled { opacity: .45; cursor: default; }

/* --- mode controls: five modes, three per row --- */
#playModeControl button { position: relative; }

/* --- dark theme --- */
:root[data-theme="dark"] .path-card,
:root[data-theme="dark"] .achievements-card,
:root[data-theme="dark"] .achievement,
:root[data-theme="dark"] .path-node__disc,
:root[data-theme="dark"] .tutorial__demo,
:root[data-theme="dark"] .tutorial__write { background: var(--white); }
:root[data-theme="dark"] .path-node.is-done .path-node__disc,
:root[data-theme="dark"] .plan-option.is-selected { background: rgba(227,138,104,.2); }
:root[data-theme="dark"] .achievement:not(.is-unlocked) .achievement__art { opacity: .3; }
:root[data-theme="dark"] .path-node.is-current .path-node__disc,
:root[data-theme="dark"] .path-card__glyph,
:root[data-theme="dark"] .chapter-card__glyph { background: var(--ink); color: var(--paper); }
:root[data-theme="dark"] .paywall-card,
:root[data-theme="dark"] .checkout-card,
:root[data-theme="dark"] .consent-card,
:root[data-theme="dark"] .chapter-card { background: var(--white); }
:root[data-theme="dark"] .heat-cell[data-level="1"] { background: #2f4a39; }
:root[data-theme="dark"] .heat-cell[data-level="2"] { background: #3f6b4c; }
:root[data-theme="dark"] .heat-cell[data-level="3"] { background: #56905f; }
:root[data-theme="dark"] .heat-cell[data-level="4"] { background: #7ec492; }
:root[data-theme="dark"] .tutorial__write { background-image: linear-gradient(rgba(229,235,217,.08) 1px, transparent 1px), linear-gradient(90deg, rgba(229,235,217,.08) 1px, transparent 1px); }

@media (prefers-reduced-motion: reduce) {
  .path-node.is-current .path-node__disc { transform: none; }
}
:root[data-theme="dark"] .offer-card .menu-secondary,
:root[data-theme="dark"] .chapter-card .menu-secondary { background: var(--paper); color: var(--ink); }

.tutorial__header { display: flex; align-items: center; gap: 8px; padding-right: 16px; }
.tutorial__header .onboarding__progress { flex: 1; }
/* Overlays sit above the bottom navigation. */
.overlay { z-index: 30; }
.toast { z-index: 60; }

/* --- home: one main action, then the path and the garden --- */
.goal-chip { display: inline-flex; align-items: center; gap: 5px; margin: 0; padding: 4px 10px 4px 7px; border: 1px solid var(--line); border-radius: 999px; background: rgba(var(--glass-rgb), .66); color: var(--ink); font-size: 11px; font-variant-numeric: tabular-nums; }
.goal-chip b { font-weight: 800; }
.goal-chip__ring { width: 14px; height: 14px; rotate: -90deg; }
.goal-chip__ring circle { fill: none; stroke: rgba(23,59,54,.14); stroke-width: 2.6; }
.goal-chip__ring .goal-chip__fill { stroke: var(--red); stroke-linecap: round; stroke-dasharray: 0 100; transition: stroke-dasharray .5s cubic-bezier(.2,.75,.25,1); }
.goal-chip.is-done { border-color: transparent; background: var(--tint-green); color: var(--green-ink); }
.goal-chip.is-done .goal-chip__fill { stroke: var(--green); }
:root[data-theme="dark"] .goal-chip__ring circle { stroke: rgba(229,235,217,.16); }
.hero-chips { margin-bottom: 12px; }

.today-card h2 { margin-bottom: 12px; }
.today-card .today-sub { margin: -8px 0 12px; }
/* Goal met: the card says so and its button steps back. */
.today-card.is-done .menu-primary { border: 1px solid rgba(255,255,255,.34); background: rgba(255,255,255,.08); color: #fffef9; }
.today-card.is-done .menu-primary:hover { background: rgba(255,255,255,.16); }
.today-links { display: flex; flex-wrap: wrap; justify-content: center; gap: 2px 6px; margin-top: 6px; }
.today-link { min-height: 36px; padding: 0 10px; border: 0; border-radius: 12px; background: none; color: rgba(255,255,255,.82); font: inherit; font-size: 13px; font-weight: 800; cursor: pointer; }
.today-link:hover { background: rgba(255,255,255,.08); color: white; }
.today-link b { margin-left: 2px; color: #e7a89b; font-variant-numeric: tabular-nums; }

.card-chevron { flex: none; margin-left: auto; color: var(--ink-soft); font-size: 22px; font-weight: 600; line-height: 1; }

.garden-card { display: block; width: 100%; padding: 14px; border: 1px solid var(--line); border-radius: 20px; background: rgba(var(--glass-rgb), .7); color: var(--ink); font: inherit; text-align: left; cursor: pointer; }
.garden-card__head { display: flex; align-items: center; gap: 8px; font-size: 16px; }
.garden-card__head b { font-weight: 800; letter-spacing: -.02em; }
.garden-card__count { display: block; margin: 2px 0 10px; color: var(--ink-soft); font-size: 13px; font-weight: 600; }
.garden-card__count > b { color: var(--ink); font-size: 22px; font-weight: 800; font-variant-numeric: tabular-nums; letter-spacing: -.03em; }
.garden-card .stack-legend { margin-top: 8px; }
/* --- listening, reading, HSK 1 mock (formats.js) --- */
.segmented--sm button:last-child:nth-child(odd) { grid-column: 1 / -1; }
.format-prompt { display: flex; flex-direction: column; align-items: center; gap: 10px; margin: 2px 0 4px; }
.format-prompt[hidden] { display: none; }
.format-listen { display: inline-flex; align-items: center; gap: 10px; min-height: 64px; padding: 0 26px 0 20px; border: 0; border-radius: 99px; background: linear-gradient(135deg, #fa8466, #cf4934); color: white; font-size: 15px; font-weight: 800; box-shadow: 0 8px 20px rgba(223,85,63,.28); cursor: pointer; }
.format-listen:active { transform: scale(.96); }
.format-listen.is-playing svg { animation: format-pulse .9s ease-in-out infinite alternate; }
@keyframes format-pulse { from { opacity: .55; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .format-listen.is-playing svg { animation: none; } }
.format-picture { width: min(100%, 240px); aspect-ratio: 1; object-fit: contain; border-radius: 20px; background: var(--muted); }
.format-prompt__text, .format-prompt__ask { width: 100%; text-align: center; }
.format-zh { margin: 0; font: 600 clamp(22px, 7vw, 30px)/1.4 "Noto Serif SC", serif; overflow-wrap: anywhere; }
.format-prompt[data-format="text"] .format-prompt__text .format-zh { font-size: clamp(19px, 5.6vw, 23px); text-align: left; }
.format-prompt[data-format="text"] .format-prompt__text .format-pinyin { text-align: left; }
.format-prompt__ask { padding-top: 10px; border-top: 1px dashed var(--line); }
.format-prompt__ask .format-zh { font-size: clamp(18px, 5.4vw, 22px); color: var(--red-dark); }
.format-pinyin { margin: 4px 0 0; color: var(--ink-soft); font-size: 13px; font-weight: 600; line-height: 1.4; }
.format-hint { margin: 0; color: var(--ink-soft); font-size: 14px; font-style: italic; text-align: center; }
.probe-option--zh { display: flex; flex-direction: column; align-items: center; gap: 2px; font: 600 20px/1.35 "Noto Serif SC", serif; }
.probe-option--zh small { color: var(--ink-soft); font: 600 12px/1.3 "Manrope", system-ui, sans-serif; }
.probe__options--pictures { grid-template-columns: 1fr 1fr; }
.probe__options--pictures.has-three { grid-template-columns: repeat(3, 1fr); }
.probe-option--picture { display: grid; place-items: center; min-height: 0; padding: 6px; aspect-ratio: 1; }
.probe-option--picture img { width: 100%; height: 100%; object-fit: contain; border-radius: 11px; }
.probe-option--picture img.is-loading { opacity: 0; }
.result-sections { display: grid; gap: 6px; width: min(100%, 300px); margin: 12px auto 0; padding: 0; list-style: none; }
.result-sections[hidden] { display: none; }
.result-sections li { display: flex; justify-content: space-between; gap: 12px; padding: 8px 14px; border: 1px solid var(--line); border-radius: 14px; background: rgba(var(--glass-rgb), .7); font-size: 13px; font-weight: 700; }
.mock-card { display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 4px 12px; }
.mock-card__seal { display: grid; width: 48px; height: 48px; place-items: center; border-radius: 14px; background: var(--tint-red); color: var(--red-dark); font: 600 26px "Noto Serif SC", serif; }
.mock-card__copy h2 { margin: 0; font-size: 17px; }
.mock-card__copy p { margin: 3px 0 0; color: var(--ink-soft); font-size: 12px; line-height: 1.45; }
.mock-card__start { grid-column: 1 / -1; margin-top: 10px; }
/* The narrowest phones: path labels stay inside the screen. */
@media (max-width: 340px) { .path-node__label { width: 104px; } }

/* --- shine: cards in "Освоил" ------------------------------------------ *
 * A foil plate with a light sweep every few seconds.
 * --shine-delay staggers tiles so a grid never flashes all at once.
 * :root[data-shine="holo"] swaps the gold foil for a holographic one. */
:root {
  --shine-foil: linear-gradient(135deg, #fff5d9 0%, #f6d98f 34%, #fff2cc 56%, #eac267 100%);
  --shine-edge: #d4a246;
  --shine-ink: #9a3a1f;
  --shine-glow: rgba(201, 151, 59, .38);
  --shine-accent: #c38a1e;
  --shine-light: rgba(255, 255, 255, .8);
}
:root[data-theme="dark"] {
  --shine-foil: linear-gradient(135deg, #4b3b1b 0%, #7d5f25 36%, #574420 58%, #8f6c2b 100%);
  --shine-edge: #d4a246;
  --shine-ink: #ffe2a0;
  --shine-glow: rgba(212, 162, 70, .3);
  --shine-accent: #f3c867;
  --shine-light: rgba(255, 236, 190, .45);
}
:root[data-shine="holo"], [data-swatch="holo"] {
  --shine-foil: linear-gradient(125deg, #ffdbe9 0%, #dcecff 24%, #dcfbe6 48%, #fff3cf 72%, #ecdcff 100%);
  --shine-edge: #b99be0;
  --shine-ink: #5b3a8c;
  --shine-glow: rgba(160, 120, 220, .32);
  --shine-accent: #8f6cd6;
}
:root[data-shine="holo"][data-theme="dark"], :root[data-theme="dark"] [data-swatch="holo"] {
  --shine-foil: linear-gradient(125deg, #5a3450 0%, #2f4a6e 24%, #2e5a45 48%, #6a5a2c 72%, #4b3470 100%);
  --shine-ink: #f1e4ff;
  --shine-accent: #d7c2ff;
}
/* The gold swatches in settings stay gold while holo is on. */
:root[data-shine="holo"] .shine-swatch:not([data-swatch="holo"]) {
  --shine-foil: linear-gradient(135deg, #fff5d9 0%, #f6d98f 34%, #fff2cc 56%, #eac267 100%);
  --shine-edge: #d4a246;
  --shine-ink: #9a3a1f;
  --shine-glow: rgba(201, 151, 59, .38);
  --shine-accent: #c38a1e;
}
:root[data-shine="holo"][data-theme="dark"] .shine-swatch:not([data-swatch="holo"]) {
  --shine-foil: linear-gradient(135deg, #4b3b1b 0%, #7d5f25 36%, #574420 58%, #8f6c2b 100%);
  --shine-ink: #ffe2a0;
  --shine-glow: rgba(212, 162, 70, .3);
  --shine-accent: #f3c867;
}
.shine { position: relative; overflow: hidden; isolation: isolate; border-color: var(--shine-edge) !important; background: var(--shine-foil) !important; background-size: 100% 100%; color: var(--shine-ink) !important; box-shadow: 0 3px 12px var(--shine-glow); }
:root[data-shine="holo"] .shine:not(.shine-swatch), .shine-swatch[data-swatch="holo"] { background-size: 220% 220% !important; animation: shine-holo 6s ease-in-out infinite alternate; }
.shine::after { content: ""; position: absolute; z-index: -1; inset: -30% -60%; background: linear-gradient(110deg, transparent 38%, var(--shine-light) 50%, transparent 62%); transform: translateX(-70%); animation: shine-sweep 5s ease-in-out var(--shine-delay, 0s) infinite; pointer-events: none; }
@keyframes shine-sweep { 0%, 72% { transform: translateX(-70%); } 100% { transform: translateX(70%); } }
@keyframes shine-holo { from { background-position: 0% 50%; } to { background-position: 100% 50%; } }

/* The page of a mastered character: the big glyph on its own foil plate. */
.detail-hanzi.shine { width: fit-content; padding: 10px 24px 14px; border: 2px solid; border-radius: 28px; }

/* Chapter sheet: mastered characters on a small foil chip, no motion. */
.chapter-words span.is-mastered { padding: 0 4px; border-radius: 7px; background: var(--shine-foil); color: var(--shine-ink); box-shadow: 0 1px 4px var(--shine-glow); }

/* Result: everything this round mastered, together, each with one burst. */
.result-mastered { margin: 14px 0 18px; text-align: center; }
.result-mastered h2 { margin: 0 0 10px; color: var(--shine-accent); font-size: 12px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase; }
.result-mastered__tiles { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; }
.result-mastered__tile { display: grid; place-items: center; min-width: 64px; height: 64px; padding: 0 12px; border: 2px solid; border-radius: 18px; font: 600 30px/1 "Noto Serif SC", serif; white-space: nowrap; cursor: pointer; }
.shine--burst { animation: shine-pop .7s cubic-bezier(.3, 1.5, .5, 1) calc(var(--shine-delay, 0s) + .25s) both; }
.shine--burst::after { animation: shine-sweep-once 1s ease-out calc(var(--shine-delay, 0s) + .55s) 1 both, shine-sweep 5s ease-in-out calc(var(--shine-delay, 0s) + 3s) infinite; }
@keyframes shine-pop { 0% { opacity: 0; transform: scale(.4) rotate(-8deg); } 60% { opacity: 1; transform: scale(1.14) rotate(3deg); } 100% { transform: none; } }
@keyframes shine-sweep-once { from { transform: translateX(-70%); } to { transform: translateX(70%); } }

/* Settings: a small sample of each look. */
.shine-options button { display: inline-flex; align-items: center; gap: 7px; }
.shine-swatch { display: inline-grid; place-items: center; width: 26px; height: 26px; border: 1.5px solid; border-radius: 8px; font: 600 15px/1 "Noto Serif SC", serif; }

/* "Без анимации" (and the system's reduced motion): the foil stays, nothing moves. */
:root[data-shine="still"] .shine, :root[data-shine="still"] .shine--burst, [data-swatch="still"] { animation: none !important; }
:root[data-shine="still"] .shine::after, [data-swatch="still"]::after { display: none; }
@media (prefers-reduced-motion: reduce) {
  .shine, .shine::after, .shine--burst { animation: none !important; }
  .shine::after { display: none; }
}
