/* Hanyu front end. Always dark: lacquer, graphite, one cinnabar accent (see DESIGN.md). */
@font-face {
  font-family: "Kai";
  src: url("fonts/kai.woff2") format("woff2");
  font-display: swap;
}
:root {
  color-scheme: dark;
  --ground: #0a0a0b;
  --raised: #161618;
  --nested: #1f1f22;
  --line: rgba(255, 255, 255, 0.08);
  --text: #f4f3f1;
  --text-2: #a3a2a8;
  --text-3: #6f6e75;
  --accent: #e5482f;
  --accent-soft: rgba(229, 72, 47, 0.16);
  --right: #34c77b;
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ui: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue", "PingFang SC", sans-serif;
  --kai: "Kai", "Kaiti SC", "STKaiti", serif;
  --tabbar: calc(56px + env(safe-area-inset-bottom));
}
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { margin: 0; background: var(--ground); color: var(--text); }
body {
  font: 17px/1.3 var(--ui);
  -webkit-font-smoothing: antialiased;
  min-height: 100dvh;
  overscroll-behavior-y: none;
}
::selection { background: var(--accent-soft); color: var(--text); }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 8px; }

/* ---------- screen ---------- */
.view {
  padding: calc(env(safe-area-inset-top) + 12px) 20px calc(var(--tabbar) + 28px);
  max-width: 560px;
  margin: 0 auto;
}
.large-title { font-size: 34px; line-height: 41px; font-weight: 700; letter-spacing: -0.022em; margin: 8px 0 2px; }
.subtitle { color: var(--text-2); font-size: 15px; margin: 0 0 20px; }

/* ---------- today ---------- */
.ring-wrap { position: relative; width: 232px; height: 232px; margin: 12px auto 8px; }
.ring-wrap svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.ring-track { fill: none; stroke: var(--nested); stroke-width: 22; }
.ring-fill {
  fill: none; stroke: var(--accent); stroke-width: 22; stroke-linecap: round;
  transition: stroke-dashoffset 900ms var(--ease-out);
}
.ring-center { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; }
.ring-pct { font-size: 52px; font-weight: 700; letter-spacing: -0.03em; font-variant-numeric: tabular-nums; line-height: 1; }
.ring-pct small { font-size: 24px; font-weight: 600; color: var(--text-2); margin-left: 1px; }
.ring-label { color: var(--text-2); font-size: 15px; margin-top: 6px; }

.figures { display: grid; grid-template-columns: repeat(3, 1fr); margin: 20px 0 24px; }
.figure { text-align: center; }
.figure + .figure { border-left: 1px solid var(--line); }
.figure b { display: block; font-size: 24px; font-weight: 650; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; }
.figure span { color: var(--text-2); font-size: 13px; }

.pill {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; height: 56px; border-radius: 999px;
  background: var(--accent); color: #fff; font-weight: 600; font-size: 17px;
  transition: transform 120ms var(--ease-out), opacity 120ms;
}
.pill.quiet { background: var(--raised); color: var(--text); margin-top: 10px; }
.pill:active { transform: scale(0.97); }
.pill[disabled] { opacity: 0.4; }

.group { background: var(--raised); border-radius: 14px; margin-top: 28px; overflow: hidden; }
.cell { display: flex; align-items: center; gap: 12px; min-height: 52px; padding: 12px 16px; }
.cell + .cell { border-top: 1px solid var(--line); }
.cell .label { flex: 1; }
.cell .value { color: var(--text-2); font-variant-numeric: tabular-nums; }
.cell .glyph { font-family: var(--kai); font-size: 26px; width: 34px; text-align: center; color: var(--accent); }

.empty { color: var(--text-2); text-align: center; margin-top: 30vh; }
.hanzi-kai { font-family: var(--kai); }

/* ---------- tab bar ---------- */
.tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 10;
  height: var(--tabbar); padding-bottom: env(safe-area-inset-bottom);
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); /* as many tabs as there are */
  background: rgba(10, 10, 11, 0.72);
  backdrop-filter: blur(24px) saturate(160%); -webkit-backdrop-filter: blur(24px) saturate(160%);
  border-top: 1px solid var(--line);
}
.tabbar[hidden] { display: none; }
.tab { display: grid; justify-items: center; align-content: center; gap: 3px; color: var(--text-3); font-size: 10.5px; font-weight: 500; letter-spacing: 0.01em; }
.tab svg { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; transition: transform 120ms var(--ease-out); }
.tab:active svg { transform: scale(0.94); }
.tab[aria-current="page"] { color: var(--text); }

/* ---------- unlock ---------- */
.field {
  width: 100%; height: 52px; border-radius: 14px; border: 1px solid var(--line);
  background: var(--raised); color: var(--text); font: inherit; padding: 0 16px; margin: 8px 0 12px; caret-color: var(--accent);
}
.error { color: var(--accent); font-size: 15px; margin: 0 0 12px; }

@media (prefers-reduced-motion: reduce) {
  .ring-fill { transition: none; }
}

/* ---------- study ---------- */
.study { min-height: 100dvh; display: flex; flex-direction: column; max-width: 560px; margin: 0 auto; }
.study-top {
  position: sticky; top: 0; z-index: 5; display: flex; align-items: center; gap: 14px;
  padding: calc(env(safe-area-inset-top) + 8px) 16px 10px;
  background: rgba(10, 10, 11, 0.8); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
}
.bar { flex: 1; height: 4px; border-radius: 2px; background: var(--nested); overflow: hidden; }
.bar > div { height: 100%; background: var(--accent); transform-origin: left; transition: transform 300ms var(--ease-out); }
.count { color: var(--text-2); font-size: 15px; font-variant-numeric: tabular-nums; min-width: 28px; text-align: right; }
.study-body { flex: 1; padding: 8px 20px 24px; }
.study-foot {
  position: sticky; bottom: 0; padding: 12px 20px calc(env(safe-area-inset-bottom) + 12px);
  background: linear-gradient(to top, var(--ground) 70%, rgba(10, 10, 11, 0));
}
.foot-stack { display: grid; gap: 10px; }
.split { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.split .pill.quiet { margin-top: 0; }

.round {
  width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center;
  background: var(--raised); color: var(--text); transition: transform 120ms var(--ease-out);
}
.round:active { transform: scale(0.94); }
.round svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.round.ghost { background: transparent; color: var(--text-2); width: 36px; height: 36px; }
.listen { display: flex; gap: 10px; }
.word .round { background: var(--nested); }

.question { color: var(--text-2); font-size: 15px; margin: 18px 0 10px; text-align: center; }
.prompt { display: grid; place-items: center; min-height: 150px; margin-bottom: 18px; }
.prompt .listen .round { width: 72px; height: 72px; }
.prompt .listen .round svg { width: 30px; height: 30px; }
.prompt-hanzi { font-family: var(--kai); font-size: 88px; line-height: 1.1; text-align: center; }
.prompt-meaning { font-size: 26px; font-weight: 600; letter-spacing: -0.01em; text-align: center; padding: 0 8px; }

.choices { display: grid; gap: 10px; }
.choices.grid { grid-template-columns: 1fr 1fr; }
.choice {
  min-height: 60px; padding: 14px 16px; border-radius: 14px; text-align: left;
  background: var(--raised); border: 1.5px solid transparent;
  transition: transform 120ms var(--ease-out), background-color 160ms, border-color 160ms;
}
.choice:active { transform: scale(0.98); }
.choice-hanzi { font-family: var(--kai); font-size: 40px; text-align: center; min-height: 92px; }
.choice[disabled] { cursor: default; }
.choice.is-right { border-color: var(--right); background: rgba(52, 199, 123, 0.12); }
.choice.is-wrong { border-color: var(--accent); background: var(--accent-soft); }
.fr { color: var(--text-2); font-size: 14px; margin-top: 2px; }
.muted { color: var(--text-2); }
.small { font-size: 14px; }

.verdict { font-weight: 650; font-size: 17px; margin: 22px 0 10px; }
.verdict.right { color: var(--right); }
.verdict.wrong { color: var(--accent); }

.badge { display: inline-block; margin: 14px 0 8px; padding: 4px 10px; border-radius: 999px; background: var(--accent-soft); color: var(--accent); font-size: 13px; font-weight: 600; }

/* the word card */
.word { background: var(--raised); border-radius: 20px; padding: 20px; }
.word-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; }
.word-hanzi { font-family: var(--kai); font-size: 64px; line-height: 1.05; }
.word-pinyin { font-size: 20px; color: var(--text-2); margin-top: 4px; }
.senses { margin-top: 16px; display: grid; gap: 8px; font-size: 18px; }
.tip { color: var(--text-2); font-size: 15px; line-height: 1.4; margin: 12px 0 0; }
.chars { margin-top: 16px; border-top: 1px solid var(--line); }
.char { display: flex; gap: 14px; align-items: center; padding: 12px 0; }
.char + .char { border-top: 1px solid var(--line); }
.char-glyph { font-family: var(--kai); font-size: 40px; width: 64px; text-align: center; flex: none; }
.char-big { font-family: var(--kai); font-size: 22px; }
.char-text { line-height: 1.35; }
.strokes { width: 64px; height: 64px; flex: none; border-radius: 12px; background: var(--nested); cursor: pointer; }
.strokes path { fill: var(--text); transition: fill 200ms; }
.strokes path.todo { fill: rgba(255, 255, 255, 0.1); }
.strokes path.now { fill: var(--accent); }

/* pinyin keyboard */
.typed {
  min-height: 56px; display: flex; align-items: center; justify-content: center;
  font-size: 30px; font-weight: 500; letter-spacing: 0.01em; margin: 4px 0 14px;
  white-space: pre; /* a space typed at the end shows, like a normal keyboard */
}
.placeholder { color: var(--text-3); font-size: 20px; }
.caret { width: 2px; height: 30px; background: var(--accent); margin-left: 2px; animation: blink 1s steps(1) infinite; }
@keyframes blink { 50% { opacity: 0; } }
.pad { display: grid; gap: 8px; user-select: none; -webkit-user-select: none; }
.pad-row { display: flex; gap: 6px; justify-content: center; }
.key {
  flex: 1; max-width: 40px; height: 46px; border-radius: 8px; background: var(--nested);
  font-size: 20px; display: grid; place-items: center; }
.key:active { transform: scale(0.95); background: #2c2c30; }
.key.wide { max-width: 56px; flex: 1.4; }
.key svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linejoin: round; stroke-linecap: round; }
.tones .key.tone { max-width: none; color: var(--accent); font-weight: 600; background: var(--accent-soft); }
.tones .key.space { max-width: none; flex: 2; font-size: 15px; color: var(--text-2); }

/* checkpoint and end */
.pause { text-align: center; padding-top: 6vh; }
.pause-glyph { font-size: 96px; color: var(--accent); line-height: 1.1; }
.pause-title { font-size: 28px; font-weight: 700; letter-spacing: -0.02em; margin: 14px 0 8px; }
.pause .muted { max-width: 32ch; margin: 0 auto; line-height: 1.45; }
.cell.head { color: var(--text-2); font-size: 13px; min-height: 40px; }
.cell-hanzi { font-size: 30px; min-width: 64px; }
.study-foot .pill.quiet { margin-top: 10px; }

@media (prefers-reduced-motion: reduce) {
  .bar > div, .choice, .key { transition: none; }
  .caret { animation: none; }
}

/* ---------- book ---------- */
.lessons { margin-top: 8px; }
.lesson-row { display: flex; align-items: center; gap: 14px; width: 100%; padding: 14px 14px 14px 16px; text-align: left; transition: background-color 120ms; }
.lesson-row + .lesson-row { border-top: 1px solid var(--line); }
.lesson-row:active, .row-button:active { background: var(--nested); }
.lesson-row > svg, .row-button > svg { width: 18px; height: 18px; flex: none; fill: none; stroke: var(--text-3); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.lesson-num { width: 28px; flex: none; color: var(--text-3); font-size: 15px; font-variant-numeric: tabular-nums; }
.lesson-text { flex: 1; display: grid; gap: 2px; min-width: 0; }
.lesson-zh { font-size: 22px; line-height: 1.2; }
.lesson-en { color: var(--text-2); font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.meter { display: block; height: 3px; border-radius: 2px; background: var(--nested); margin-top: 8px; overflow: hidden; }
.meter > span { display: block; height: 100%; background: var(--accent); transform-origin: left; }
.lesson-count { color: var(--text-2); font-size: 14px; font-variant-numeric: tabular-nums; white-space: nowrap; }

.back-link { display: inline-flex; align-items: center; gap: 2px; color: var(--accent); font-size: 17px; height: 44px; margin-left: -6px; }
.back-link svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.lesson-hero { text-align: center; margin: 12px 0 4px; }
.lesson-hero-zh { font-size: 56px; line-height: 1.15; }
.lesson-hero-sub { color: var(--text-2); font-size: 15px; margin-top: 6px; }
.center { text-align: center; }
.section-title { font-size: 22px; font-weight: 700; letter-spacing: -0.015em; margin: 32px 0 10px; }
.section-title + .group { margin-top: 0; }
.row-button { width: 100%; text-align: left; transition: background-color 120ms; }
.row-zh { font-size: 20px; }
.one-line { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 52vw; }
.label { min-width: 0; }

.dots { display: inline-flex; gap: 5px; flex: none; }
.dots i { width: 7px; height: 7px; border-radius: 50%; background: var(--nested); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12); }
.dots i.on { background: var(--right); box-shadow: none; }
/* the signature: a mastered word is stamped with a cinnabar seal of its characters */
.seal {
  flex: none; min-width: 34px; height: 34px; padding: 0 4px; display: grid; place-items: center;
  border-radius: 5px; background: var(--accent); color: #fff4ef; font-size: 17px; line-height: 1;
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.18); transform: rotate(-3deg);
}

/* bottom sheet */
.layer { position: fixed; inset: 0; z-index: 20; }
.scrim { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.55); opacity: 0; transition: opacity 280ms var(--ease-out); }
.scrim.open { opacity: 1; }
.scrim:not(.open) { transition-duration: 200ms; }
.sheet {
  position: absolute; left: 0; right: 0; bottom: 0; max-height: 88dvh; overflow-y: auto;
  background: var(--raised); border-radius: 22px 22px 0 0; padding: 8px 4px calc(env(safe-area-inset-bottom) + 16px);
  transform: translateY(100%); transition: transform 320ms cubic-bezier(0.32, 0.72, 0, 1);
  box-shadow: 0 -8px 30px rgba(0, 0, 0, 0.4);
}
.sheet.open { transform: translateY(0); }
.sheet:not(.open) { transition-duration: 200ms; } /* exits snap faster than they enter */
.sheet .word { background: transparent; }
.sheet .handle, .sheet .word-head { touch-action: none; }
.handle { width: 36px; height: 5px; border-radius: 3px; background: rgba(255, 255, 255, 0.2); margin: 0 auto 4px; }
@media (prefers-reduced-motion: reduce) { .sheet { transform: none; opacity: 0; transition: opacity 150ms ease; } .sheet.open { opacity: 1; } }

/* ---------- dialogues ---------- */
.levels { margin-top: 20px; }
.row-button.locked { opacity: 0.45; cursor: default; }
.row-button > svg:last-child { width: 18px; height: 18px; }
.step-num { width: 28px; height: 28px; flex: none; border-radius: 50%; display: grid; place-items: center; background: var(--nested); color: var(--text-2); font-size: 14px; font-weight: 600; font-variant-numeric: tabular-nums; }
.step-num.passed { background: var(--right); color: #06210f; }
.tag { font-size: 13px; font-weight: 600; color: var(--right); }
.tag.due { color: var(--accent); }
.hint { color: var(--text-2); font-size: 15px; text-align: center; margin: 4px 0 14px; }
.scene { text-align: center; padding: 10vh 8px 0; display: grid; gap: 10px; font-size: 20px; }
.bubble { background: var(--raised); border-radius: 20px 20px 20px 6px; padding: 16px 18px; margin: 6px 0 14px; }
.bubble.mine { border-radius: 20px 20px 6px 20px; background: #2a1712; box-shadow: inset 0 0 0 1px rgba(229, 72, 47, 0.28); }
.bubble .who { color: var(--text-2); font-size: 13px; font-weight: 600; margin-bottom: 6px; }
.bubble .zh { font-size: 30px; line-height: 1.3; }
.bubble .py { color: var(--text-2); font-size: 16px; margin: 4px 0 8px; }
.bubble .en { font-size: 16px; margin-bottom: 12px; }
.bubble .en.big { font-size: 22px; font-weight: 600; }
.bubble .round { background: var(--nested); width: 40px; height: 40px; }
.choice-zh { font-size: 24px; }
.tiles { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; min-height: 56px; margin: 10px 0; }
.tiles.answer { border-bottom: 1px solid var(--line); padding-bottom: 12px; }
.tile { padding: 8px 14px; border-radius: 12px; background: var(--raised); font-size: 24px; transition: transform 120ms var(--ease-out); }
.tile:active { transform: scale(0.94); }
.tiles.answer .tile { background: var(--nested); }
.result-num { font-size: 64px; font-weight: 700; letter-spacing: -0.03em; color: var(--accent); }
.study-foot .split .pill.quiet { margin-top: 0; }
.prompt-meaning .fr { font-weight: 400; font-size: 15px; letter-spacing: 0; margin-top: 6px; }

/* ---------- exam ---------- */
.countdown { text-align: center; margin: 18px 0 6px; }
.countdown-num { font-size: 72px; font-weight: 700; letter-spacing: -0.04em; line-height: 1; color: var(--accent); font-variant-numeric: tabular-nums; }
.countdown .muted { margin-top: 8px; font-size: 15px; }
.pad-group { padding: 16px; display: grid; gap: 12px; }
.pad-group .small { margin: 0; line-height: 1.4; }
.pad-group .pill.quiet { margin-top: 0; }
.range { display: flex; align-items: flex-end; gap: 10px; }
.range label { flex: 1; display: grid; gap: 6px; color: var(--text-2); font-size: 13px; }
.range > .muted { padding-bottom: 16px; }
.range .field { margin: 0; height: 46px; background: var(--nested); border-color: transparent; }
.select { appearance: none; -webkit-appearance: none; text-align: center; }
.score { font-size: 22px; font-weight: 700; min-width: 64px; color: var(--accent); font-variant-numeric: tabular-nums; }
.prompt-zh { font-size: 30px; line-height: 1.4; text-align: center; padding: 0 6px; }
.prompt-col { display: grid; gap: 10px; text-align: center; }
.blank { display: inline-block; min-width: 1.6em; border-bottom: 2px solid var(--accent); margin: 0 2px; }
.choice-py { font-size: 22px; text-align: center; }
.question b { color: var(--text); font-weight: 600; }
.section-score { display: grid; gap: 8px; }
.section-score-head { display: flex; justify-content: space-between; font-size: 15px; }
.section-score .meter { margin: 0; }
.pad-group .pill.quiet { background: var(--nested); }
.range .field { text-align: center; }
.choice-hanzi.long { font-size: 28px; }

/* ---------- me ---------- */
.streak { text-align: center; margin: 10px 0 0; }
.streak-num { font-size: 72px; font-weight: 700; letter-spacing: -0.04em; line-height: 1; font-variant-numeric: tabular-nums; }
.streak .muted { margin-top: 6px; font-size: 15px; }
.field.inline { width: auto; height: 36px; margin: 0; padding: 0 10px; background: var(--nested); border: 0; border-radius: 9px; font-size: 16px; color: var(--text); }
.select-right { max-width: 56%; text-align: right; }
.cell.accent { color: var(--accent); }
.footnote { color: var(--text-2); font-size: 13px; line-height: 1.4; margin: 8px 16px 0; }
.status { margin: 0; }
.pad-group .field { margin: 0; background: var(--nested); border-color: transparent; }
input[type="date"]::-webkit-calendar-picker-indicator { filter: invert(0.8); }

/* ---------- motion (see DESIGN.md: one authored moment per screen, feedback fast, exits faster) ---------- */
@keyframes enter { from { opacity: 0; transform: translateY(6px); } }
@keyframes fade { from { opacity: 0; } }
@keyframes stamp {
  0% { opacity: 0; transform: scale(1.7) rotate(-9deg); }
  70% { opacity: 1; transform: scale(0.96) rotate(-3deg); }
  100% { opacity: 1; transform: scale(1) rotate(-3deg); }
}
/* questions arrive instantly: they are seen 100+ times a session (review-animations) */
/* after an answer: the verdict, then the card a beat later */
.study-body .verdict, .study-body .verdict ~ .word { animation: fade 140ms var(--ease-out) both; }
.study-body .verdict ~ .mastered { animation: enter 220ms var(--ease-out) both; }
.mastered { display: flex; align-items: center; gap: 14px; background: var(--accent-soft); border-radius: 16px; padding: 14px 16px; margin-bottom: 12px; }
.mastered b { font-size: 17px; }
.seal.stamp { width: 52px; height: 52px; font-size: 24px; animation: stamp 420ms cubic-bezier(0.23, 1, 0.32, 1) 120ms both; }
.cell.row-button, .lesson-row { -webkit-user-select: none; user-select: none; }
.cell.row-button:active > svg, .lesson-row:active > svg { transform: translateX(2px); transition: transform 120ms var(--ease-out); }

@media (prefers-reduced-motion: reduce) {
  .study-body .verdict ~ .mastered { animation: fade 150ms ease both; }
  .seal.stamp { animation: fade 200ms ease both; transform: rotate(-3deg); }
}
.pad[hidden] { display: none; }

/* ---------- screen transitions (app/motion.js), iOS-like ---------- */
:root { --ease-ios: cubic-bezier(0.32, 0.72, 0, 1); }
/* what stays put while the page moves: the tab bar, and in a session its top bar and bottom button */
.tabbar { view-transition-name: tabbar; }
html[data-nav="next"] .study-top { view-transition-name: study-top; }
html[data-nav="next"] .study-foot { view-transition-name: study-foot; }
::view-transition-group(*) { animation-duration: 380ms; animation-timing-function: var(--ease-ios); }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 380ms; animation-timing-function: var(--ease-ios); animation-fill-mode: both; mix-blend-mode: normal; }

@keyframes in-right { from { transform: translateX(100%); } }
@keyframes out-left { to { transform: translateX(-28%); filter: brightness(0.6); } }
@keyframes in-left { from { transform: translateX(-28%); filter: brightness(0.6); } }
@keyframes out-right { to { transform: translateX(100%); } }
@keyframes in-up { from { transform: translateY(100%); } }
@keyframes stay-back { to { transform: scale(0.94); filter: brightness(0.55); border-radius: 22px; } }
@keyframes come-forward { from { transform: scale(0.94); filter: brightness(0.55); } }
@keyframes out-down { to { transform: translateY(100%); } }
@keyframes vt-fade-in { from { opacity: 0; } }
@keyframes vt-fade-out { to { opacity: 0; } }
@keyframes next-in { from { transform: translateX(14%); opacity: 0; } }
@keyframes next-out { to { transform: translateX(-10%); opacity: 0; } }

/* open a page: it slides in from the right, the page below moves back and dims */
html[data-nav="push"]::view-transition-old(root) { animation-name: out-left; }
html[data-nav="push"]::view-transition-new(root) { animation-name: in-right; box-shadow: -10px 0 30px rgba(0, 0, 0, 0.5); }
/* Back: the exact reverse */
html[data-nav="pop"]::view-transition-old(root) { animation-name: out-right; z-index: 2; box-shadow: -10px 0 30px rgba(0, 0, 0, 0.5); }
html[data-nav="pop"]::view-transition-new(root) { animation-name: in-left; }
/* a session or an exam rises like a full-screen sheet… */
html[data-nav="up"]::view-transition-old(root) { animation-name: stay-back; }
html[data-nav="up"]::view-transition-new(root) { animation-name: in-up; animation-duration: 440ms; }
/* …and drops back down when you leave (faster: exits snap) */
html[data-nav="down"]::view-transition-old(root) { animation-name: out-down; animation-duration: 320ms; z-index: 2; }
html[data-nav="down"]::view-transition-new(root) { animation-name: come-forward; animation-duration: 320ms; }
/* the next question: a short slide, the bar and the button stay in place */
html[data-nav="next"]::view-transition-old(root) { animation-name: next-out; animation-duration: 200ms; }
html[data-nav="next"]::view-transition-new(root) { animation-name: next-in; animation-duration: 260ms; }
/* tabs: a quick cross-fade */
html[data-nav="fade"]::view-transition-old(root) { animation-name: vt-fade-out; animation-duration: 160ms; }
html[data-nav="fade"]::view-transition-new(root) { animation-name: vt-fade-in; animation-duration: 200ms; }

/* swipe back (app/motion.js): the page follows the finger over the page under it */
html { touch-action: pan-y; }
#app { position: relative; z-index: 1; background: var(--ground); min-height: 100dvh; }
#app.dragging { box-shadow: -12px 0 30px rgba(0, 0, 0, 0.55); will-change: transform; }
#app.settling { box-shadow: -12px 0 30px rgba(0, 0, 0, 0.55); transition: transform 260ms var(--ease-ios); }
.underlay { position: fixed; inset: 0; z-index: 0; overflow: hidden; background: var(--ground); pointer-events: none; transform: translateX(-28%); filter: brightness(0.82); }
.underlay.settling { transition: transform 260ms var(--ease-ios), filter 260ms var(--ease-ios); }
/* iOS dims the page under a push lightly, not to black */
@keyframes out-left { to { transform: translateX(-28%); filter: brightness(0.82); } }
@keyframes in-left { from { transform: translateX(-28%); filter: brightness(0.82); } }

/* ---------- iOS 26 shapes: everything round, concentric with the iPhone's corners ---------- */
:root { --r-card: 24px; --r-control: 18px; --glass: rgba(38, 38, 42, 0.62); --glass-line: rgba(255, 255, 255, 0.09); }
.group, .word, .mastered, .sheet .word { border-radius: var(--r-card); }
.choice, .tile, .field, .range .field, .bubble { border-radius: var(--r-control); }
.bubble { border-radius: 22px 22px 22px 8px; }
.bubble.mine { border-radius: 22px 22px 8px 22px; }
.key { border-radius: 12px; }
.strokes { border-radius: 16px; }
.field.inline { border-radius: 999px; padding: 0 14px; }

/* floating round controls (Back, close): a small disc of dark glass */
.back-link, .study-top .round.ghost {
  width: 44px; height: 44px; margin: 0; padding: 0; border-radius: 50%;
  display: grid; place-items: center; color: var(--text);
  background: var(--glass); box-shadow: inset 0 0 0 1px var(--glass-line), 0 4px 14px rgba(0, 0, 0, 0.35);
  backdrop-filter: blur(20px) saturate(160%); -webkit-backdrop-filter: blur(20px) saturate(160%);
  transition: transform 120ms var(--ease-out);
}
.back-link:active, .study-top .round.ghost:active { transform: scale(0.92); }
.back-link svg { width: 22px; height: 22px; margin-left: -2px; }
.study-top .round.ghost svg { width: 18px; height: 18px; }
.view > .back-link:first-child { position: sticky; top: calc(env(safe-area-inset-top) + 8px); z-index: 4; }

/* the tab bar floats like the Apple TV app's (iOS 26): a slim capsule of clear glass sitting low,
   over the home-bar area; the page shows through it, blurred; the current tab in a soft pill,
   tinted with the accent */
.tabbar {
  left: 20px; right: 20px; bottom: max(8px, calc(env(safe-area-inset-bottom) - 12px));
  height: 58px; padding: 5px; border-radius: 999px; border-top: 0; gap: 2px;
  background: rgba(30, 30, 34, 0.58);
  box-shadow: inset 0 0.5px 0 rgba(255, 255, 255, 0.22), inset 0 0 0 0.5px rgba(255, 255, 255, 0.12), 0 8px 28px rgba(0, 0, 0, 0.42);
  backdrop-filter: blur(22px) saturate(190%); -webkit-backdrop-filter: blur(22px) saturate(190%);
}
.tab { border-radius: 999px; gap: 2px; color: var(--text-2); font-size: 10px; letter-spacing: 0.015em; transition: background-color 200ms var(--ease-out), color 200ms var(--ease-out); }
.tab svg { width: 22px; height: 22px; }
.tab[aria-current="page"] { background: rgba(255, 255, 255, 0.11); color: var(--accent); }
.tab[aria-current="page"] span, .tab[aria-current="page"] { font-weight: 600; }
.view { padding-bottom: calc(env(safe-area-inset-bottom) + 84px); }

@media (prefers-reduced-transparency: reduce) {
  .tabbar, .back-link, .study-top .round.ghost { background: #26262a; backdrop-filter: none; -webkit-backdrop-filter: none; }
}
.lesson-hero-zh { font-size: clamp(34px, 12vw, 56px); text-wrap: balance; }

/* iPhone zooms into any text field under 16px and stays zoomed: every field is at least 17px
   (the number fields inherited 13px from their label) */
input, select, textarea, .field, .range .field, .field.inline { font-size: 17px; }

/* the one dangerous action: iOS system red, asked in a sheet first */
:root { --danger: #ff453a; }
.cell.danger { color: var(--danger); }
.sheet.alert { padding: 8px 20px calc(env(safe-area-inset-bottom) + 20px); text-align: center; display: grid; gap: 10px; }
.sheet.alert .pause-title { margin: 10px 0 0; }
.sheet.alert p { margin: 0 auto; max-width: 34ch; line-height: 1.45; }
.sheet.alert .pill.quiet { margin-top: 0; background: var(--nested); }
.danger-pill { background: var(--danger); color: #fff; margin-top: 8px; }

/* ---------- install card, install guide, share ---------- */
.install-card { display: flex; align-items: center; gap: 12px; background: var(--raised); border-radius: var(--r-card); padding: 12px 12px 12px 14px; margin: 4px 0 8px; }
.install-card img { border-radius: 11px; flex: none; }
.install-card .label { flex: 1; line-height: 1.3; }
.install-go { width: auto; height: 36px; padding: 0 16px; font-size: 15px; }
.install-x { width: 30px; height: 30px; border-radius: 50%; color: var(--text-2); background: var(--nested); font-size: 13px; flex: none; }
.steps { list-style: none; margin: 4px 0; padding: 0; display: grid; gap: 12px; text-align: left; }
.steps li { display: flex; gap: 12px; align-items: flex-start; line-height: 1.4; }
.step-n { flex: none; width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center; background: var(--accent-soft); color: var(--accent); font-weight: 650; font-size: 14px; }
.share { justify-items: center; }
.qr { width: 196px; height: 196px; padding: 10px; background: #fff; border-radius: 20px; }
.qr svg { width: 100%; height: 100%; display: block; }
.share .split { width: 100%; }

/* ---------- segmented control (Book tab: the book in class) ---------- */
.segmented { display: flex; gap: 2px; padding: 3px; margin: 10px 0 12px; background: var(--raised); border-radius: 999px; }
.segmented button { flex: 1; min-height: 34px; border-radius: 999px; font-size: 15px; font-weight: 600; color: var(--text-2); transition: background-color 200ms var(--ease-out), color 200ms var(--ease-out); }
.segmented button[aria-checked="true"], .segmented button[aria-pressed="true"] { background: var(--nested); color: var(--text); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4); }
@media (prefers-reduced-motion: reduce) { .segmented button { transition: none; } }
.cell .segmented.chips { margin: 0; flex: 0 0 auto; min-width: 132px; }
.cell .segmented.chips button { min-height: 30px; padding: 0 12px; }
/* book chips: several can be on, so "on" must read at a glance (cinnabar tint), "off" stays quiet */
.segmented.chips button[aria-pressed="true"] { background: var(--accent-soft); color: var(--text); box-shadow: inset 0 0 0 1px rgba(229, 72, 47, 0.45); }
.cell .segmented.chips { background: var(--nested); }

/* ---------- Words to fix ---------- */
.fix-list .cell { gap: 12px; }
.fix-meta { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }

/* ---------- Can't listen now ---------- */
.cant-listen { display: inline-flex; align-items: center; gap: 6px; margin: 14px auto 0; padding: 8px 16px; min-height: 44px; border-radius: 999px; color: var(--text-2); font-size: 15px; background: var(--raised); }
.cant-listen svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.cant-listen:active { transform: scale(0.97); }
.prompt:has(.cant-listen) { flex-direction: column; }

/* ---------- Listening mode ---------- */
.listen-mode .listen-row { display: block; width: 100%; text-align: left; opacity: 0.45; transition: opacity 240ms var(--ease-out), box-shadow 240ms var(--ease-out); }
.listen-mode .listen-row.is-now { opacity: 1; box-shadow: inset 0 0 0 1.5px rgba(229, 72, 47, 0.55); }
.listen-mode .listen-title { margin: 18px 0 6px; }
.listen-controls { display: flex; align-items: center; justify-content: center; gap: 18px; }
.listen-controls .pill { flex: 1; max-width: 220px; margin: 0; }
.listen-controls .round svg { width: 20px; height: 20px; }
@media (prefers-reduced-motion: reduce) { .listen-mode .listen-row { transition: none; } }
.listen-mode .scene { padding: 6px 8px 14px; font-size: 17px; }

/* the Chinese of a memory tip, with its pinyin under it */
.tip-zh { display: flex; flex-direction: column; margin: 2px 0 4px; } /* on its own line, the English after it */
.tip-zh .hanzi-kai { color: var(--text); font-size: 17px; line-height: 1.35; }
.tip-py { color: var(--text-2); font-size: 13px; line-height: 1.3; }
.round svg circle { fill: none; }
.round[aria-label="Listen slowly"] svg { width: 27px; height: 27px; } /* the turtle: big enough to read */
.prompt .listen .round[aria-label="Listen slowly"] svg { width: 36px; height: 36px; }

/* ---------- Loading (first screen, in index.html) ---------- */
.loading { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; padding: 24px; text-align: center; }
.loading img { border-radius: 22px; }
.loading-text { margin: 10px 0 0; font-size: 17px; font-weight: 600; color: var(--text); }
.loading-bar { width: 180px; height: 4px; border-radius: 999px; background: var(--raised); overflow: hidden; }
.loading-bar > div { height: 100%; background: var(--accent); transform: scaleX(0); transform-origin: left; transition: transform 300ms var(--ease-out); }
.loading-note { max-width: 260px; margin: 6px 0 0; font-size: 13px; color: var(--text-2); line-height: 1.4; }

/* iOS 26, opened from the Home Screen: while a page is shorter than the screen, iOS sizes the
   screen short by the status bar (WebKit bug 301108), so the tab bar starts too high and drops
   into place at the first scroll. A page at least as tall as the screen gets the full size. */
@media (display-mode: standalone) {
  html { min-height: min(100lvh, calc(100% + env(safe-area-inset-top))); }
}
