/* Practice: hub, round, speaking. Kit tokens only (tokens.css, motion.css); every transition uses the motion tokens,
   so reduced motion is handled there. Phone (390px) first. */

/* ---------- hub ---------- */
.practice { padding-top: var(--s-2); }
.practice .page-head .caption { white-space: nowrap; }
.practice.has-dock { padding-bottom: 92px; }
.pr-queue { display: grid; gap: var(--s-4); padding: var(--s-5); border-radius: var(--r-card); background: var(--surface); box-shadow: inset 0 0 0 1px var(--hairline); }
.pr-queue-top { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--s-3); flex-wrap: wrap; }
.pr-due { display: flex; align-items: baseline; gap: var(--s-2); }
.pr-due .figure { min-width: 1ch; }
.pr-new { color: var(--ink-2); }
.pr-empty { color: var(--ink-2); }
@media (max-width: 899px) {
  .pr-queue-btn { position: fixed; inset-inline-start: 0; inset-inline-end: 0; bottom: calc(57px + env(safe-area-inset-bottom)); z-index: calc(var(--z-bar) - 1);
    padding: var(--s-3) max(var(--gutter), env(safe-area-inset-left)) var(--s-2); background: linear-gradient(to bottom, transparent, var(--canvas) 34%); }
  .pr-queue-btn .btn { box-shadow: var(--shadow-lift); }
  :root:has(.pr-queue-btn) { scroll-padding-bottom: calc(57px + 84px + env(safe-area-inset-bottom)); }
}
@media (max-width: 899px) and (prefers-reduced-transparency: reduce) { .pr-queue-btn { background: var(--canvas); } }
.pr-ready { display: grid; gap: var(--s-2); }
.pr-ready-top { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s-3); }
.pr-ready-top b { font-weight: 500; font-size: 15px; }
/* recall bar: seen (quiet) under recall (ink); the fill springs (kit .fill) */
.pr-bar { height: 6px; }
.pr-bar .pr-seen { position: absolute; inset: 0; border-radius: inherit; background: var(--cell-learning); transform-origin: left; transform: scaleX(var(--p, 0)); transition: transform var(--dur-fill) var(--spring-soft); }
.pr-bar .fill { z-index: 1; }
.pr-rows { margin-top: var(--s-5); }
.pr-rows .row:first-child { border-top: 0; }
.practice > .section { margin-top: var(--s-8); padding-top: var(--s-6); }
.pr-areas { display: grid; }
.pr-area { display: grid; grid-template-columns: minmax(0, 1fr) 16px; grid-template-areas: "top chev" "bar chev"; align-items: center; gap: var(--s-2) var(--s-3); padding: var(--s-3) 0; min-height: 64px; border-bottom: 1px solid var(--hairline); color: var(--ink); text-decoration: none; }
.pr-area-top { grid-area: top; display: flex; justify-content: space-between; align-items: baseline; gap: var(--s-3); }
.pr-area .track { grid-area: bar; }
.pr-area > .icon { grid-area: chev; color: var(--ink-3); }
.pr-foot { margin-top: var(--s-6); --gap: var(--s-2); }
/* the now card: the plan's next row over the queue numbers */
.pr-next { display: grid; gap: var(--s-1); padding-bottom: var(--s-4); border-bottom: 1px solid var(--hairline); }
.pr-next-title { font: 500 var(--fs-title)/1.3 var(--font-ui); color: var(--ink); }
.pr-round-link { justify-self: start; }
/* the three groups: the heading is the button that opens and closes its rows (kit .reveal-answer motion) */
.practice > .pr-group { margin-top: var(--s-6); padding-top: var(--s-2); }
.pr-group > h2 { margin: 0; font: inherit; }
.pr-group > h2 + * { margin-top: 0; }
.pr-group-head { display: grid; grid-template-columns: minmax(0, 1fr) auto 16px; align-items: center; gap: var(--s-3); width: 100%; min-height: var(--tap); padding: var(--s-3) 0;
  border: 0; background: none; color: var(--ink); text-align: start; cursor: pointer; }
.pr-group-title { font: 400 var(--fs-h2)/1.15 var(--font-display); letter-spacing: -0.01em; }
.pr-group-head .row-trail { color: var(--ink-2); }
.pr-group-head > .icon { color: var(--ink-3); transform: rotate(90deg); transition: transform var(--dur-base) var(--spring-soft); }
.pr-group-head[aria-expanded="false"] > .icon { transform: rotate(0deg); }
.pr-group-head:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.pr-group-panel .pr-rows { margin-top: 0; }
:root[data-motion="reduce"] .pr-group-head > .icon { transition: none; }
@media (prefers-reduced-motion: reduce) { :root:not([data-motion="full"]) .pr-group-head > .icon { transition: none; } }
@media (min-width: 900px) {
  .pr-queue-btn { display: block; }
  .pr-queue-btn .btn { width: auto; min-width: 280px; }
  .practice.has-dock { padding-bottom: 0; }
}
@media (min-width: 960px) {
  .practice { max-width: 760px; }
}

/* ---------- round (full screen, no chrome) ---------- */
body.pr-in-round { overflow: hidden; }
body.pr-in-round #view { max-width: none; padding: 0; }
.pr-round { position: fixed; inset: 0 0 auto 0; height: 100dvh; z-index: var(--z-bar); display: grid; grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr) auto; background: var(--canvas);
  padding: env(safe-area-inset-top) max(var(--gutter), env(safe-area-inset-left)) 0; }
.pr-round.is-flow { position: static; height: auto; min-height: 100dvh; }
.pr-top { padding-top: var(--s-3); max-width: 640px; width: 100%; margin: 0 auto; }
.pr-top-row { display: flex; justify-content: space-between; align-items: center; gap: var(--s-3); margin-top: 2px; }
.pr-top-row > .caption { white-space: nowrap; flex: none; }
.pr-strip { width: var(--w, 94px); max-width: 40vw; flex: none; margin-inline-start: auto; }
.pr-end { min-height: var(--tap); padding: 0 10px; margin-inline-end: -10px; }
.pr-scroll { overflow-y: auto; overscroll-behavior: contain; padding: var(--s-2) 0 var(--s-3); -webkit-overflow-scrolling: touch; }
.pr-card { max-width: 640px; margin: 0 auto; padding: var(--s-5) var(--s-5) var(--s-4); }
.pr-card .prompt { margin-top: var(--s-3); font-size: clamp(22px, 6.4vw, var(--fs-prompt)); }
.pr-card .answer { margin-top: var(--s-6); align-items: flex-end; }
.pr-card .answer-input { resize: none; overflow: hidden; display: block; line-height: 24px; min-height: 52px; padding: 14px 0 12px; }
.pr-card .answer .check { margin-bottom: 14px; }
.pr-tbar { margin-top: var(--s-3); height: 2px; }
.pr-tbar .fill { background: var(--hairline-strong); transform-origin: left; transition: none; }   /* a timer is never accent */
.pr-tbar.is-over .fill { background: var(--ink-3); }
.pr-tbar.is-repair .fill { background: var(--ink); }
.pr-secs { min-width: 4ch; text-align: end; }
.pr-newtag { color: var(--accent-ink); }
.pr-promptbox > * + * { margin-top: var(--s-2); }
.pr-task { color: var(--ink-2); font-size: 14px; }
.pr-partner { font: 400 20px/1.35 var(--font-display); }
.pr-source { margin-top: var(--s-3); }
.pr-context { margin-top: var(--s-2); }
.pr-help { margin-top: var(--s-3); }
.pr-chosen { margin-top: var(--s-3); }
.pr-gap { display: inline-block; min-width: 3.2em; margin: 0 0.1em; border-bottom: 2px solid var(--accent); vertical-align: baseline; }
.pr-hl { background: var(--accent-soft); color: inherit; border-radius: 3px; padding: 0 2px; box-decoration-break: clone; -webkit-box-decoration-break: clone; }
.pr-prefill { flex: none; padding: 14px 0 12px; color: var(--ink-2); font: 400 var(--fs-input)/24px var(--font-ui); max-width: 45%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.answer.is-retype .answer-input { text-decoration: none; color: var(--ink); animation: none; }
.answer.is-shake .answer-input { animation: nudge 300ms var(--ease-out); }
/* the verdict sweep (motion.css) lies on the field's rule: the 1px border and the 1px focus shadow under it, so a
   checked answer shows one 2px line in green or red, not a coloured line over a black one */
.answer::after { bottom: -2px; }
/* wrong → type it once (design A7): the struck answer fades (120 ms) before the field empties, then the empty field
   rises 8 px into its new state (160 ms) instead of both changing in one frame. Reduced motion: no fade, no rise. */
.answer.is-clearing .answer-input { opacity: 0; transition: opacity 120ms var(--ease-in); }
.answer.is-retype.is-arriving .answer-input { animation: pr-retype-in var(--dur-quick) var(--ease-out) both; }
@keyframes pr-retype-in { from { opacity: 0; transform: translateY(calc(8px * var(--move))); } }
.pr-moves { display: grid; gap: var(--s-2); margin-top: var(--s-5); }
.pr-moves .btn { justify-content: flex-start; min-height: 52px; }
.pr-fb { display: grid; gap: var(--s-2); padding-top: var(--s-4); }
.pr-res { font-weight: 500; }
.pr-res.is-ok { color: var(--ok); }
.pr-res.is-bad { color: var(--bad); }
.pr-res.is-warn { color: var(--ink); }
.pr-yours { font-size: 17px; }
.pr-diff { font-size: 17px; line-height: 1.4; }
.pr-diff.answer-key { font: 400 20px/1.35 var(--font-display); margin-top: 0; }
.pr-diff .caption { font-family: var(--font-ui); }
.pr-wrongword { text-decoration: line-through; text-decoration-color: var(--bad); text-decoration-thickness: 1.5px; color: var(--ink-2); }
.answer-key mark, .pr-diff mark { background: none; color: inherit; text-decoration: underline 2px var(--ok); text-underline-offset: 4px; }   /* the words to learn, on the right answer: never red */
.pr-study { font: 400 24px/1.3 var(--font-display); }
.pr-study.is-long { font-size: 20px; }
.pr-rule { color: var(--ink-2); font-size: 14px; padding: 10px 12px; background: var(--surface-2); border-radius: var(--r-tile); }
.pr-notes p + p { margin-top: 6px; }
.pr-hint { color: var(--ink); font-weight: 500; }
.pr-also { font-size: 14px; color: var(--ink-2); }
.pr-more summary { cursor: pointer; color: var(--accent-ink); font-size: 13px; min-height: var(--tap); display: inline-flex; align-items: center; }
.pr-word { padding: var(--s-3); border-radius: var(--r-ctl); background: var(--surface-2); display: grid; gap: 4px; }
.pr-claude .btn { min-height: var(--tap); font-size: 14px; }
.pr-back { margin-top: var(--s-1); }
.pr-actions { max-width: 640px; width: 100%; margin: 0 auto; padding: var(--s-2) 0 calc(var(--s-3) + env(safe-area-inset-bottom)); background: var(--canvas); }
.pr-actions .btn-primary { flex: 1; min-height: 52px; font-size: 16px; }
.pr-actions .btn-quiet { min-height: 52px; }
.pr-round .segments { margin-top: var(--s-1); }

/* keyboard mode (core/keyboard.js, AUDIT §5.5): the header is one 32 px row (segments, count, End); the card loses
   its padding and fills the column; the prompt is 22 px and three lines at most; feedback, the answer to retype and
   the word panel open above the field; the field sits at the bottom of the column, right over the action row, which
   sits on the keyboard (44 px buttons, no safe-area padding). */
body.kb .pr-top { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; column-gap: var(--s-3); min-height: 32px; padding-top: 0; }
body.kb .pr-top > .segments { margin-top: 0; grid-row: 1; }
body.kb .pr-top .pr-again, body.kb .pr-top .pr-strip, body.kb .pr-top kbd { display: none; }
body.kb .pr-top-row { display: contents; }
body.kb .pr-top .pr-end { position: relative; min-height: 32px; }
body.kb .pr-top .pr-end::before { content: ""; position: absolute; inset: -6px 0; }   /* a 44 px target in a 32 px row */
body.kb .pr-scroll { display: flex; flex-direction: column; padding: var(--s-1) 0 0; }
body.kb .pr-scroll > .pr-card { flex: 1 0 auto; display: flex; flex-direction: column; width: 100%; padding: 0; background: transparent; box-shadow: none; border-radius: 0; }
body.kb .pr-card .prompt { margin-top: var(--s-2); font-size: 22px; line-height: 1.25; }
body.kb .pr-card .prompt:not(:has(.pr-gap)) { --kb-lines: 3; }
body.kb .pr-card .pr-task, body.kb .pr-card .pr-context { --kb-lines: 2; }
body.kb .pr-card .pr-tbar { margin-top: var(--s-2); }
body.kb .pr-card .pr-source, body.kb .pr-card .pr-help { margin-top: var(--s-1); }
body.kb .pr-card > .reveal-answer { order: 1; }
body.kb .pr-card > .pr-moves { order: 2; }
body.kb .pr-card > .answer { order: 3; position: sticky; bottom: 0; z-index: 1; margin-top: auto; padding-top: var(--s-2); background: var(--canvas); }
body.kb .pr-card .pr-fb { padding-top: var(--s-3); padding-bottom: var(--s-2); }
body.kb .pr-actions { padding: 4px 0 6px; }
body.kb .pr-actions .btn-primary, body.kb .pr-actions .btn-quiet { min-height: var(--tap); }
body.kb .pr-actions kbd { display: none; }
@media (min-width: 720px) {
  .pr-card { padding: var(--s-8) var(--s-8) var(--s-6); }
  .pr-scroll { padding-top: var(--s-6); }
}

/* ---------- done ---------- */
.pr-done { max-width: 640px; margin: 0 auto; padding: calc(var(--s-8) + env(safe-area-inset-top)) max(var(--gutter), env(safe-area-inset-left)) var(--s-10); --gap: var(--s-4); }
.pr-done h1, .pr-done-h { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0 var(--s-2); margin-top: var(--s-2); }
.pr-done-of { font-size: var(--fs-h2); color: var(--ink-2); }
.pr-done-hero { --gap: var(--s-3); }
.pr-done-hero > * + * { margin-top: var(--s-3); }
.pr-done .pr-ready { margin-top: var(--s-5); }
.pr-done-field { margin-top: var(--s-3); }
.pr-list { margin-top: var(--s-10) !important; padding-top: var(--s-6); border-top: 1px solid var(--hairline); }
.pr-list h2 { font-size: 20px; margin-bottom: var(--s-2); }
.pr-list .list-item { font: 400 19px/1.35 var(--font-display); }
.pr-list .list-item .caption { font-family: var(--font-ui); }
.pr-next { color: var(--ink-2); }
.pr-done-actions { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-5); }
.pr-done-actions .btn { min-height: 48px; }
.pr-done-actions .btn-primary { flex: 1 1 220px; }
/* a done screen is an ordinary page (done-hero.js leaveRound): its actions stay on screen above the tab bar while the
   page scrolls, so Another round and Done are always in reach */
.pr-done .pr-done-actions, .wr-done .pr-done-actions { position: sticky; bottom: calc(57px + env(safe-area-inset-bottom)); z-index: 3;
  margin-inline: calc(-1 * var(--s-2)); padding: var(--s-3) var(--s-2) var(--s-2); background: linear-gradient(to bottom, transparent, var(--canvas) 28%); }
@media (min-width: 900px) { .pr-done .pr-done-actions, .wr-done .pr-done-actions { bottom: 0; } }
@media (prefers-reduced-transparency: reduce) { .pr-done .pr-done-actions, .wr-done .pr-done-actions { background: var(--canvas); } }
/* The done page's arrival (done-hero.js arrive(), design A3). html[data-arrive="done"] is set before the route's view
   transition starts, so the old picture has the round card as its own layer: it lifts away (300 ms, as "I know this"
   does) while the round's header and buttons fade with the page and the done page rises in its place on the soft
   spring. The bars slide back on their own layers (motion.css fx-bar, fx-tabs). Reduced motion: no view transition,
   a 140 ms crossfade. */
:root[data-arrive="done"] .pr-round .pr-card { view-transition-name: pr-done-card; }
:root[data-arrive="done"]::view-transition-old(pr-done-card) { animation: vt-lift 300ms var(--ease-out) both; }
:root[data-arrive="done"]::view-transition-old(fx-roundhead), :root[data-arrive="done"]::view-transition-old(fx-roundact) { display: block; animation: vt-fade-out var(--dur-quick) var(--ease-in) both; }
:root[data-arrive="done"][data-vt="view"]::view-transition-new(fx-view) { animation: vt-rise var(--dur-card) var(--spring-soft) 60ms both; }
/* the figure is an odometer (done-hero.js): the next digit's serif is masked at the window's edges, as on Today */
.pr-done-hero .figure.odo { -webkit-mask-image: linear-gradient(transparent 0, #000 12%, #000 84%, transparent 96%); mask-image: linear-gradient(transparent 0, #000 12%, #000 84%, transparent 96%); margin-bottom: -0.1em; }
/* what the round added to the exam items known, in accent next to the count (design A4) */
.pr-ready-n { display: inline-flex; align-items: baseline; gap: var(--s-2); }
.pr-gain { color: var(--accent); font-weight: 600; font-size: 15px; }

/* ---------- speaking ---------- */
.pr-speak .pr-card { margin: var(--s-4) 0 0; max-width: none; }
.pr-speak .pr-top-row { padding-top: var(--s-4); }
.pr-micbox { display: grid; justify-items: center; gap: var(--s-2); margin-top: var(--s-6); }
.pr-mic { display: grid; place-items: center; width: 84px; height: 84px; border-radius: 50%; border: 0; background: var(--ink); color: var(--on-ink); cursor: pointer; }
.pr-mic[data-state="listening"] { background: var(--accent); color: var(--on-accent); box-shadow: 0 0 0 6px var(--accent-soft); }
.pr-mic[data-state="error"] { background: var(--surface-2); color: var(--ink-2); }
.pr-mic-l { text-align: center; max-width: 34ch; }
.pr-heard { min-height: 1.5em; font: 400 20px/1.35 var(--font-display); color: var(--ink-2); }
/* outdoors: the level meter (kit .track .fill, quick and linear; still with reduced motion: JS steps it 4 times a
   second), the loud-room line, hold to talk and typing instead */
.pr-meter { width: 120px; height: 4px; }
.pr-meter[hidden] { display: none; }
.pr-meter .fill { background: var(--accent); transition-duration: 90ms; transition-timing-function: linear; }
.pr-meter.is-still .fill { transition: none; }
.pr-loud { text-align: center; max-width: 34ch; color: var(--ink); }
.pr-loud[hidden] { display: none; }
.pr-micopts { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s-2); }
.pr-micopts[hidden] { display: none; }
.pr-holdtoggle[aria-pressed="true"] { color: var(--ink); box-shadow: inset 0 0 0 1.5px var(--ink-2); }
.pr-holdtoggle.is-offered { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.pr-type { display: flex; gap: var(--s-2); width: 100%; }
.pr-type[hidden] { display: none; }
.pr-unsure { display: grid; gap: 4px; width: 100%; justify-items: start; }
.pr-unsure[hidden] { display: none; }
.pr-mic { touch-action: manipulation; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.pr-spoken { min-height: 52px; padding: 10px 0; margin-top: var(--s-5); }
.pr-checks { width: 100%; border-collapse: collapse; font-size: 14px; }
.pr-checks td { padding: 8px 0; border-bottom: 1px solid var(--hairline); }
.pr-checks td + td { text-align: end; }
.pr-checks .is-ok { color: var(--ok); }
.pr-checks .is-bad { color: var(--bad); }
.pr-typein { display: flex; gap: var(--s-2); margin-top: var(--s-4); }
.pr-bullets { margin: 0; padding-inline-start: 1.2em; color: var(--ink-2); }
.pr-topic { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; }
.pr-folien { margin: 0; padding-inline-start: 1.4em; display: grid; gap: var(--s-3); }
.pr-folien li { padding-inline-start: var(--s-1); }
.pr-cue { display: block; margin-top: 2px; }
.pr-run { padding-top: calc(var(--s-6) + env(safe-area-inset-top)); --gap: var(--s-4); }
.pr-clock { font-size: clamp(84px, 28vw, 168px); }
.pr-folie { font: 400 24px/1.25 var(--font-display); }
.pr-runbar { height: 6px; }
.pr-audio { width: 100%; }

/* with a hardware keyboard and room to spare, the buttons sit under the card instead of at the bottom edge */
@media (hover: hover) and (pointer: fine) and (min-width: 720px) {
  .pr-round { grid-template-rows: auto auto auto; align-content: start; overflow-y: auto; }
  .pr-scroll { overflow: visible; }
  .pr-actions { padding-top: var(--s-4); }
}

/* ▶ on exam-word cards: the example's recording (services/audio.js) */
.pr-word-ex { display: flex; align-items: center; gap: var(--s-1); }
.pr-play { flex: none; display: grid; place-items: center; width: var(--tap); min-height: var(--tap); margin-block: -8px; margin-inline: -12px 0; border: 0; border-radius: var(--r-ctl); background: transparent; color: var(--ink); cursor: pointer; }
.pr-play:hover { background: var(--surface-2); }

/* ---------- Schreiben (#/practice/write) and Build an email (write.js). Kit tokens only. ---------- */
.wr-page .section h2 { font-size: 22px; }
.wr-about { color: var(--ink-2); font-size: 14px; }
.wr-fns { margin-top: var(--s-4); }
.wr-fns > summary, .wr-task > summary, .wr-modeltext > summary { cursor: pointer; min-height: var(--tap); display: flex; align-items: center; gap: var(--s-2); font-weight: 500; color: var(--ink-2); list-style: none; }
.wr-fns > summary::-webkit-details-marker, .wr-task > summary::-webkit-details-marker, .wr-modeltext > summary::-webkit-details-marker { display: none; }
.wr-fns > summary::before, .wr-task > summary::before, .wr-modeltext > summary::before { content: ""; width: 7px; height: 7px; border-inline-end: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg); transition: transform var(--dur-base) var(--spring-snappy); margin-block: 0; margin-inline: 2px 4px; }
.wr-fns[open] > summary::before, .wr-task[open] > summary::before, .wr-modeltext[open] > summary::before { transform: rotate(45deg); }
.wr-fn h3 { margin-top: var(--s-5); font: 600 13px/1.35 var(--font-ui); color: var(--ink-2); letter-spacing: 0.01em; }
.wr-phrase { display: grid; justify-content: stretch; gap: 2px; }
.wr-phrase [lang="de"] { font: 400 18px/1.35 var(--font-display); }

.wr-build { --gap: var(--s-5); }
.wr-build .page-head { display: block; }
.wr-build .page-head h1 { margin-top: var(--s-1); }
.wr-task { padding: var(--s-3) var(--s-4) var(--s-4); border-radius: var(--r-ctl); background: var(--surface-2); }
.wr-task[open] > summary { margin-bottom: var(--s-2); }
.wr-task > * + * { margin-top: var(--s-3); }
.wr-situation { font: 400 17px/1.45 var(--font-display); }
.wr-quote { margin: 0; padding-inline-start: var(--s-3); border-inline-start: 2px solid var(--hairline-strong); font: italic 400 16px/1.45 var(--font-display); color: var(--ink-2); }
.wr-points { margin: 0; padding-inline-start: 1.3em; display: grid; gap: var(--s-2); font: 400 16px/1.4 var(--font-display); }
.wr-points li { padding-inline-start: var(--s-1); transition: color var(--dur-base) var(--ease-out); }
.wr-points li.is-now { color: var(--accent-ink); }
.wr-points li.is-done { color: var(--ink-2); }
.wr-points li.is-done::marker { color: var(--ok); }

/* the email: a sheet of paper that fills line by line */
.wr-letterbox { padding: var(--s-5); border-radius: var(--r-card); background: var(--surface); box-shadow: inset 0 0 0 1px var(--hairline); }
.wr-letterbox > .label { margin-bottom: var(--s-3); }
.wr-letter { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; font: 400 18px/1.5 var(--font-display); }
.wr-line { min-height: 1.5em; }
.wr-line.is-open, .wr-line.is-sign { margin: 0; }
.wr-line.is-open.is-filled { margin-bottom: var(--s-2); }
.wr-line.is-sign { margin-top: var(--s-2); }
.wr-line.is-gap { min-height: 0; height: var(--s-1); }
/* an empty line of the letter: a rule at the text's baseline with its label at the end; 40% wide for the greeting,
   the closing and the sign-off; the current line's rule is accent and 2px (you, now) */
.wr-slot { display: flex; justify-content: flex-end; align-items: flex-end; width: 100%; min-height: 27px; padding-bottom: 3px; border-bottom: 1px solid var(--field-border);
  color: var(--ink-3); font: 400 12px/1 var(--font-ui); transition: border-color var(--dur-base) var(--ease-out); }
.wr-line.is-open .wr-slot, .wr-line.is-close .wr-slot, .wr-line.is-sign .wr-slot { width: 40%; }
.wr-line.is-now .wr-slot { border-bottom: 2px solid var(--accent); padding-bottom: 2px; color: var(--accent-ink); }
/* the finished email: lines land one after another; a line kept with a slip is marked and opens its right form */
.wr-done .wr-letter .wr-in { animation: land 520ms var(--spring-pop) both; animation-delay: calc(var(--i) * 70ms); }
/* a line accepted with a slip: right, so marked in accent (dotted: it opens its right form), never red */
.wr-fixme { all: unset; cursor: pointer; text-decoration: underline 2px dotted var(--accent); text-underline-offset: 5px; border-radius: 4px; }
.wr-fixme:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.wr-fixnote { display: block; margin: 2px 0 var(--s-2); font-family: var(--font-ui); }
.wr-fixnote[hidden] { display: none; }
.wr-done-data { display: grid; gap: var(--s-4); }
.wr-points li.land { animation: land 520ms var(--spring-pop) both; }
.wr-build .wr-card { scroll-margin-bottom: calc(16px + env(safe-area-inset-bottom)); }
.wr-build .card-actions .btn { scroll-margin-bottom: calc(16px + env(safe-area-inset-bottom)); }
.wr-letter.is-post .wr-line.is-filled + .wr-line.is-filled { margin-top: 0; }
.wr-text.is-model { color: var(--ink-2); }
.wr-fly { display: inline; }
.wr-answer .wr-fly { position: absolute; left: 0; top: 12px; pointer-events: none; visibility: hidden; font: 400 18px/1.5 var(--font-display); }
/* connectors: the grammar layer's glue role (DESIGN.md: role colours on word tiles), lit when the line lands */
mark.wr-glue { color: inherit; background: transparent; border-radius: 4px; padding: 0 2px; margin: 0 -2px; box-shadow: inset 0 -2px 0 var(--role-glue);
  transition: background-color var(--dur-fill) var(--ease-out), box-shadow var(--dur-base) var(--ease-out); }
mark.wr-glue.is-lit, .answer-key mark.wr-glue, .wr-done mark.wr-glue { background: color-mix(in oklab, var(--role-glue) var(--role-mix), transparent); box-shadow: inset 0 -3px 0 var(--role-glue); }
.answer-key mark.wr-glue { text-decoration: none; }

/* the part card */
.wr-work { --gap: var(--s-3); }
.wr-segs { margin-top: var(--s-2); }
.wr-card { padding: var(--s-5) var(--s-5) var(--s-4); }
.wr-point { margin-top: var(--s-3); font: 500 15px/1.4 var(--font-ui); color: var(--ink-2); }
.wr-cue { margin-top: var(--s-2); font: 400 22px/1.3 var(--font-display); text-wrap: pretty; }
.wr-framebox:empty { display: none; }
.wr-frame { margin-top: var(--s-4); display: flex; flex-wrap: wrap; align-items: center; gap: 4px; font: 400 18px/1.4 var(--font-display); color: var(--ink-2); }
.wr-frame .tile { font-size: 16px; color: var(--ink); }
.wr-frame-text { white-space: pre-wrap; }
.wr-answer.is-wrong .answer-input { text-decoration: none; color: var(--ink); }
.wr-card .answer { margin-top: var(--s-5); align-items: flex-end; }
.wr-card .answer-input { resize: none; overflow: hidden; display: block; line-height: 24px; min-height: 52px; padding: 14px 0 12px; }
.wr-card .answer .check { margin-bottom: 14px; }
.wr-card .card-actions .btn { min-height: 48px; }

/* done */
.wr-done .pr-done-hero h1 { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0 var(--s-2); }
.wr-usedbox { display: grid; gap: var(--s-2); }
.wr-used { flex-wrap: wrap; }
.wr-compare .seg { width: 100%; }

/* write it yourself */
.wr-free { min-height: 260px; resize: vertical; font: 400 17px/1.5 var(--font-ui); }
.wr-correction { display: grid; gap: var(--s-2); }
.wr-correction:empty { display: none; }
.wr-correction h3 { margin-top: var(--s-4); font: 400 20px/1.25 var(--font-display); }
.wr-score { font: 400 24px/1.2 var(--font-display); }
.wr-fix { font: 400 18px/1.4 var(--font-display); }
.wr-fix mark { background: none; color: inherit; text-decoration: underline 2px var(--ok); text-underline-offset: 4px; }
.wr-why { font-size: 13px; color: var(--ink-2); }
.wr-good { color: var(--ink-2); }
.wr-model { white-space: pre-line; font: 400 17px/1.5 var(--font-display); }
@media (min-width: 720px) {
  .wr-card { padding: var(--s-6) var(--s-8) var(--s-5); }
  .wr-cue { font-size: 26px; }
}

/* ---------- speaking situations (sim-view.js) ---------- */
/* picker */
.sim-lead { max-width: 34em; }
.sim-locked { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "top jump"; }
.sim-locked .row-title { color: var(--ink-2); }
.sim-locked .row-trail { white-space: normal; text-align: start; }
.sim-locked .pr-area-top { flex-direction: column; align-items: flex-start; gap: 2px; }
.sim-jump { grid-area: jump; min-height: var(--tap); padding: 0 12px; font-size: 14px; }

/* the card: setup, the other person's bubble, the goal; the answer bubble unfolds on the right */
.sim-card { display: grid; gap: var(--s-3); }
.sim-card .card-meta { margin-bottom: calc(-1 * var(--s-1)); }
.sim-setup { font: 400 15px/1.45 var(--font-ui); color: var(--ink-2); }
.sim-bubble { position: relative; display: flex; align-items: flex-start; gap: var(--s-3); width: fit-content; max-width: 94%; padding-block: var(--s-3); padding-inline: var(--s-3) var(--s-4); border-radius: 20px; }
.sim-them { background: var(--surface-2); border-end-start-radius: 6px; }
.sim-you { margin-inline-start: auto; padding-block: var(--s-3); padding-inline: var(--s-4) var(--s-3); background: var(--surface); box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--accent) 45%, transparent); border-end-end-radius: 6px; }
.sim-line { padding-top: 7px; font: 400 clamp(21px, 5.8vw, 26px)/1.25 var(--font-display); letter-spacing: -0.01em; color: var(--ink); }
.sim-w { display: inline-block; }
.sim-line.is-typed .sim-w { animation: sim-word var(--dur-base) var(--ease-out) both; animation-delay: calc(var(--i) * var(--wstep, 80ms)); }
@keyframes sim-word { from { opacity: 0; transform: translateY(calc(5px * var(--move))); } }
.sim-play { flex: none; display: grid; place-items: center; width: var(--tap); height: var(--tap); min-width: var(--tap); min-height: var(--tap); box-sizing: border-box; padding: 0; border: 0; border-radius: 50%; background: var(--surface); color: var(--ink-2); box-shadow: inset 0 0 0 1px var(--hairline-strong); cursor: pointer; }
.sim-wave { display: inline-flex; align-items: center; gap: 2px; height: 18px; }
.sim-wave i { width: 3px; height: 18px; border-radius: 2px; background: currentColor; transform: scaleY(0.4); }
.sim-wave i:nth-child(2), .sim-wave i:nth-child(4) { transform: scaleY(0.7); }
.sim-wave i:nth-child(3) { transform: scaleY(1); }
/* the other person's voice is ink; accent is kept for you (the model answer you could give) */
.is-playing > .sim-play { color: var(--accent); box-shadow: inset 0 0 0 1.5px var(--accent); }
.sim-them.is-playing > .sim-play { color: var(--ink); box-shadow: inset 0 0 0 1.5px var(--ink-2); }
.is-playing > .sim-play .sim-wave i { animation: sim-wave 640ms var(--ease-inout) infinite alternate; animation-delay: calc(var(--i) * -130ms); }
@keyframes sim-wave { from { transform: scaleY(0.25); } to { transform: scaleY(1); } }
.sim-status:empty { display: none; }
/* heard first (journey #10): the line's words wait behind "Show the words" */
.sim-linebox { display: grid; justify-items: start; min-width: 0; }
.sim-line[hidden], .sim-words[hidden] { display: none; }
.sim-words { min-height: var(--tap); padding: 0 var(--s-2); margin-inline-start: calc(-1 * var(--s-2)); font-size: 15px; color: var(--ink-2); }
/* Check with the mic: the switch in the card's meta row, the mic under the goal, what was heard above the model */
.sim-card .card-meta { align-items: center; }
.sim-mictoggle { display: inline-flex; align-items: center; gap: 6px; min-height: var(--tap); padding: 0 var(--s-2); font-size: 14px; color: var(--ink-2); }
.sim-mictoggle[aria-pressed="true"] { color: var(--ink); box-shadow: inset 0 0 0 1.5px var(--ink-2); }
.sim-micbox { margin-top: 0; }
.sim-micbox[hidden] { display: none; }
.sim-mic { width: 64px; height: 64px; }
.sim-heard { display: grid; gap: 4px; padding-bottom: var(--s-2); }
.sim-heard .pr-heard { min-height: 0; }
.sim-goal { font: 500 16px/1.4 var(--font-ui); color: var(--ink); }
.sim-goal .label { display: block; margin-bottom: 2px; color: var(--ink-3); }
.sim-say { color: var(--ink-3); }
.sim-say[hidden] { display: none; }
.sim-reveal > div { display: grid; gap: var(--s-2); }
.sim-model { text-align: end; color: var(--ink-3); padding-top: var(--s-1); }
.sim-reveal .sim-you { opacity: 0; transform: translateY(calc(10px * var(--move))) scale(calc(1 - 0.03 * var(--move))); transform-origin: right bottom;
  transition: transform var(--dur-card) var(--spring-snappy) 40ms, opacity var(--dur-base) var(--ease-out) 40ms; }
.sim-reveal.is-open .sim-you { opacity: 1; transform: none; }
/* the chunk: an accent underline that sweeps in once the answer is open */
mark.sim-chunk { background: repeating-linear-gradient(90deg, var(--ink-3) 0 2px, transparent 2px 4px) 0 100% / 0% 1px no-repeat; color: inherit; padding-bottom: 2px; }
.sim-reveal.is-open mark.sim-chunk, .sim-map mark.sim-chunk { background-size: 100% 1px; transition: background-size var(--dur-fill) var(--ease-out) 280ms; }
.sim-also { display: grid; gap: 4px; text-align: end; }
.sim-also .label { color: var(--ink-3); }
.sim-alt { font: 400 18px/1.35 var(--font-display); color: var(--ink-2); }
.sim-alt mark.sim-chunk { background-size: 100% 1px; }
.sim-later summary { min-height: var(--tap); display: flex; align-items: center; color: var(--ink-2); cursor: pointer; }
.sim-later .caption { margin: 0 0 var(--s-2); }

/* actions: Show answer, then the four grades (components.css .grade4) */
.sim-actions { display: grid; }
.sim-actions .sim-show { width: 100%; }
.sim-show[hidden] { display: none; }
/* a run of Good/Easy: the strip swells once while the ripple crosses it */
.sim-round.is-streak .pr-strip { animation: sim-swell var(--dur-ripple) var(--ease-out); }
@keyframes sim-swell { 30% { transform: scale(calc(1 + 0.12 * var(--move))); } }

/* done: the round's chunks as a little map of chat bubbles */
.sim-map { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--s-2) 6px; margin: var(--s-5) 0 0; padding: 0; list-style: none; }
.sim-map-b { display: grid; gap: 2px; max-width: 100%; padding: 7px 12px 6px; border-radius: 16px; background: var(--surface); box-shadow: inset 0 0 0 1px var(--hairline-strong);
  opacity: 0; transform: translateY(calc(10px * var(--move))) scale(calc(1 - 0.14 * var(--move))); }
.sim-map-b.is-left { border-end-start-radius: 5px; transform-origin: left bottom; }
.sim-map-b.is-right { border-end-end-radius: 5px; transform-origin: right bottom; }
.sim-map-b.is-good { box-shadow: inset 0 0 0 1.5px var(--accent); }
.sim-map-b.is-again { background: transparent; box-shadow: none; outline: 1.5px dashed var(--hairline-strong); outline-offset: -1.5px; }
.sim-map-b .caption { color: var(--ink-3); }
.sim-map-chunk { font: 400 17px/1.25 var(--font-display); color: var(--ink); }
.sim-map-b .caption { font-size: 11.5px; }
.sim-map.is-in .sim-map-b { opacity: 1; transform: none; transition: transform 560ms var(--spring-pop), opacity var(--dur-base) var(--ease-out); transition-delay: calc(140ms + var(--i) * 45ms); }

/* reduced motion: the words appear at once, the waveform holds still, nothing waits on a delay */
:root[data-motion="reduce"] .sim-line.is-typed .sim-w, :root[data-motion="reduce"] .is-playing > .sim-play .sim-wave i { animation: none; }
:root[data-motion="reduce"] .sim-map.is-in .sim-map-b, :root[data-motion="reduce"] mark.sim-chunk { transition-delay: 0ms; }
:root[data-motion="reduce"] .wr-done .wr-letter .wr-in { animation-delay: 0ms; }
@media (prefers-reduced-motion: reduce) {
  :root:not([data-motion="full"]) .sim-line.is-typed .sim-w, :root:not([data-motion="full"]) .is-playing > .sim-play .sim-wave i { animation: none; }
  :root:not([data-motion="full"]) .sim-map.is-in .sim-map-b, :root:not([data-motion="full"]) mark.sim-chunk { transition-delay: 0ms; }
  :root:not([data-motion="full"]) .wr-done .wr-letter .wr-in { animation-delay: 0ms; }
}

/* the done hero's data object (field strip, letter, ready-meter row, cluster pairs, chat bubbles) */
.pr-done-data { margin-top: var(--s-5); }

/* round progress: the planned cards are the segments; cards that come back are 2px ticks underneath */
.pr-again { display: flex; justify-content: flex-end; gap: 3px; height: 2px; margin-top: 3px; }
.pr-again[hidden] { display: none; }
.pr-again i { width: 10px; height: 2px; border-radius: 1px; background: color-mix(in oklab, var(--ink-3) 40%, transparent); }
.pr-again i.is-now { background: var(--accent); }
.pr-again i.is-done { background: var(--ink-3); }
.pr-again i.is-miss { background: var(--bad); opacity: 0.7; }
@media (forced-colors: active) { .pr-again i { background: CanvasText; } .pr-again i.is-now { background: Highlight; } }
.pr-done-data > .pr-ready { margin-top: 0; }

/* Schreiben page: each task row has its "Write it yourself" beside it */
.wr-taskrow { display: grid; grid-template-columns: minmax(0, 1fr); border-bottom: 1px solid var(--hairline); }
.wr-taskrow > .row { border-bottom: 0; }
.wr-free-link { justify-self: start; margin: -6px 0 var(--s-2); padding-inline-start: 0; color: var(--ink-2); }
/* Write it yourself: the label over the text and the optional exam clock */
.wr-freehead { display: flex; justify-content: space-between; align-items: center; gap: var(--s-3); flex-wrap: wrap; }
.wr-timebox { display: inline-flex; align-items: center; gap: var(--s-2); }
.wr-clock:empty { display: none; }
.wr-memory { white-space: normal; text-align: center; max-width: 100%; }

/* ---------- "I know this" on a new card (iknow.js) ---------- */
.pr-actions .pr-know { margin-inline-end: auto; padding: 0 12px; color: var(--ink-2); }
.sim-actions { grid-template-columns: auto minmax(0, 1fr); column-gap: var(--s-2); }
.sim-actions > * { grid-column: 1 / -1; }
.sim-actions > .pr-know:not([hidden]) { grid-column: 1; }
.sim-actions > .pr-know:not([hidden]) ~ .pr-primary { grid-column: 2; }

/* ---------- Quick sort (known/sort.js) ---------- */
.qs-top { display: grid; gap: 2px; }
.qs-track { height: 2px; margin-top: var(--s-1); }
.qs-track .fill { background: var(--accent); }
.qs-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qs-tools { justify-content: flex-end; margin-top: 0; }
.qs-tools .btn { min-height: var(--tap); padding: 0 10px; }
.qs-tools .pr-end { margin-inline-end: -10px; }
.qs-scroll { display: grid; align-items: center; }
.qs-stage { display: grid; justify-items: center; align-content: center; gap: var(--s-2); text-align: center; max-width: 640px; width: 100%; margin: 0 auto; padding: var(--s-6) 0; }
.qs-word { font: 400 clamp(44px, 13vw, 72px)/1.08 var(--font-display); letter-spacing: -0.02em; color: var(--ink); background: none; border: 0; padding: 4px 8px; min-height: var(--tap);
  cursor: pointer; overflow-wrap: anywhere; max-width: 100%; }
.qs-art { font-size: 0.5em; color: var(--ink-3); letter-spacing: 0; }
.qs-gloss { font: 400 18px/1.4 var(--font-ui); color: var(--ink-2); min-height: 1.4em; margin: 0; max-width: 32ch; }
.qs-level { margin: 0; }
.qs-meaning { min-height: var(--tap); }
.qs-actions { max-width: 640px; width: 100%; margin: 0 auto; padding: var(--s-2) 0 calc(var(--s-3) + env(safe-area-inset-bottom)); background: var(--canvas); }
.qs-btns { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-3); }
.qs-btn { display: grid; align-content: space-between; gap: var(--s-3); min-height: 108px; padding: var(--s-3) var(--s-4); border-radius: var(--r-card);
  background: var(--surface); border: 1px solid var(--hairline-strong); color: var(--ink); font: inherit; text-align: start; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.qs-btn.is-learn { text-align: end; }
.qs-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.qs-btn-top { display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); }
.qs-btn.is-know .qs-btn-top { justify-content: flex-start; }
.qs-btn.is-learn .qs-btn-top { justify-content: flex-end; }
.qs-btn-label { font: 600 20px/1.2 var(--font-ui); letter-spacing: -0.01em; }
.qs-btn kbd { font: 500 11px/1 var(--font-mono); color: var(--ink-3); padding: 3px 5px; border-radius: 5px; border: 1px solid var(--hairline-strong); }
@media (hover: none) { .qs-btn kbd, .qs-meaning kbd, .qs-tools kbd, .qs-produce kbd { display: none; } }
.qs-stack { display: flex; align-items: baseline; gap: 6px; }
.qs-btn.is-learn .qs-stack { justify-content: flex-end; }
.qs-n { display: inline-block; font: 300 30px/1 var(--font-display); font-variant-numeric: tabular-nums lining-nums; transform-origin: 50% 70%; }
.qs-how { margin: var(--s-3) 0 0; text-align: center; }
.qs-done .pr-done-hero .caption + .caption { margin-top: var(--s-1); }
/* Quick sort: the word panel under the meaning */
.qs-level .wp-meta { justify-content: center; }
.qs-panel { width: 100%; max-width: 40ch; text-align: start; }
.qs-panel:empty { display: none; }
/* Quick sort, Produce mode: the meaning, the typed answer, the grader's verdict (sort.js) */
.qs-tools .qs-mode { margin-inline-end: auto; }
.qs-produce { display: grid; gap: var(--s-2); width: 100%; max-width: 32rem; text-align: start; }
.qs-produce[hidden], .qs-recognise[hidden] { display: none; }
.qs-recognise { display: grid; justify-items: center; gap: var(--s-2); }
.qs-task { margin: 0; }
.qs-prompt { font: 400 clamp(26px, 7vw, 36px)/1.2 var(--font-display); letter-spacing: -0.01em; color: var(--ink); margin: 0; }
.qs-produce .reveal-answer .btn, .qs-skip { justify-self: start; min-height: var(--tap); }
.qs-btn:disabled { opacity: 0.45; cursor: default; }
/* Check by typing before "I know this" on a card said aloud (shared/typecheck.js) */
.pr-typecheck { display: grid; gap: var(--s-2); margin-top: var(--s-4); padding-top: var(--s-3); border-top: 1px solid var(--hairline); }
.pr-typecheck .label, .pr-typecheck .caption { margin: 0; }
.pr-typecheck-actions { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.pr-typecheck-actions .btn { min-height: var(--tap); }
@media (hover: none) { .pr-typecheck kbd { display: none; } }
.cl-wmeta:empty { display: none; }

/* ---------- the round size picker (picker.js): a bottom sheet on a phone, a card from 720px ---------- */
.has-picker a[href^="#/practice/round"], .has-picker a[href^="#/practice/situations/round"] { -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }
.rs-title { margin: 0; font: 400 var(--fs-h2)/1.15 var(--font-display); }
.rs-sub { margin: -6px 0 var(--s-1); }
.rs-opts { display: grid; gap: var(--s-2); }
.rs-opt { display: flex; align-items: center; gap: var(--s-3); width: 100%; min-height: 56px; padding: var(--s-2) var(--s-3); text-align: start; border: 1px solid var(--hairline-strong);
  border-radius: var(--r-ctl); background: var(--surface); color: var(--ink); font: inherit; cursor: pointer; }
.rs-opt[disabled] { opacity: 0.55; cursor: default; }
.rs-opt[hidden] { display: none; }
.rs-more { justify-self: start; margin-top: calc(-1 * var(--s-2)); }
.rs-opt[aria-checked="true"] { border-color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }
.rs-key { flex: none; display: grid; place-items: center; width: 22px; height: 22px; border-radius: 6px; border: 1px solid var(--hairline-strong); font: 500 12px/1 var(--font-mono); color: var(--ink-3); }
.rs-opt[aria-checked="true"] .rs-key { background: var(--ink); border-color: var(--ink); color: var(--on-ink); }
.rs-main { flex: 1; display: grid; gap: 2px; min-width: 0; }
.rs-name { font: 600 var(--fs-title)/1.3 var(--font-ui); }
.rs-why { font-size: var(--fs-label); line-height: 1.4; color: var(--ink-2); }
.rs-n { font: 400 24px/1 var(--font-display); }
.rs-row { display: flex; align-items: center; gap: var(--s-2); padding-inline-end: var(--s-2); border: 1px solid var(--hairline-strong); border-radius: var(--r-ctl); background: var(--surface); }
.rs-row > .rs-opt { flex: 1; min-width: 0; border: 0; background: transparent; }
.rs-row > .rs-opt[aria-checked="true"] { box-shadow: none; }
.rs-row.is-on { border-color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }
/* forced colours drop the inset shadow and the filled key: the chosen option gets a Highlight outline instead */
@media (forced-colors: active) {
  .rs-opt[aria-checked="true"], .rs-row.is-on { outline: 2px solid Highlight; outline-offset: -2px; }
  .rs-row > .rs-opt[aria-checked="true"] { outline: none; }
}
.rs-stepper { flex: none; display: flex; align-items: center; gap: 6px; }
.rs-step { flex: none; width: var(--tap); height: var(--tap); border-radius: var(--r-ctl); border: 1px solid var(--field-border); background: var(--surface); color: var(--ink); font: 400 22px/1 var(--font-ui); cursor: pointer; }
.rs-step[disabled] { opacity: 0.4; cursor: default; }
.rs-tick { display: inline-block; overflow: hidden; border-radius: var(--r-ctl); }
.rs-tick.is-up .rs-input { animation: rs-tick-up var(--dur-quick) var(--spring-snappy); }
.rs-tick.is-down .rs-input { animation: rs-tick-down var(--dur-quick) var(--spring-snappy); }
@keyframes rs-tick-up { from { transform: translateY(calc(45% * var(--move))); opacity: 0.4; } }
@keyframes rs-tick-down { from { transform: translateY(calc(-45% * var(--move))); opacity: 0.4; } }
.rs-input { width: 4ch; height: var(--tap); padding: 0 6px; text-align: center; border: 1px solid var(--field-border); border-radius: var(--r-ctl); background: var(--surface);
  color: var(--ink); font: 500 var(--fs-input)/1 var(--font-ui); font-variant-numeric: tabular-nums; }
.rs-input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.rs-of { margin-inline-start: 2px; font-size: var(--fs-label); color: var(--ink-2); white-space: nowrap; }
.rs-warn { margin: 0; padding: var(--s-2) var(--s-3); border-radius: var(--r-ctl); background: var(--surface-2); font-size: var(--fs-label); line-height: 1.45; color: var(--ink); }
.rs-warn[hidden] { display: none; }
.rs-start { min-height: 52px; }
.rs-tip { margin: 0; text-align: center; }
@media (hover: none) { .rs-key { display: none; } }
}
@media (hover: hover) and (pointer: fine) { .rs-tip { display: none; } }

/* ---------- Quick sort with the keyboard up (AUDIT §5.5) ----------
   The header is one row: the name, "3 of 400", the tally (the tiles' counts) and End; the mode switch and Undo wait
   until the keyboard closes. The word's line, the task and the prompt (22 px, three lines) start at the top; the
   answer, the word panel and "I knew it, typo" open above the field; the field sits on the row of Skip, Learn and
   Check, which sits on the keyboard. */
.qs-answer .answer-input { resize: none; overflow: hidden; line-height: 24px; padding: 14px 0 12px; }
.qs-tally, .qs-kbrow { display: none; }
body.kb .qs-top { grid-template-columns: minmax(0, 1fr) auto auto auto; row-gap: 0; }
body.kb .qs-top > .qs-track { grid-column: 1 / -1; grid-row: 1; margin-top: var(--s-1); }
body.kb .qs-top .qs-name, body.kb .qs-top .caption { grid-row: 2; }
body.kb .qs-top .qs-mode, body.kb .qs-top .qs-undo { display: none; }
body.kb .qs-top .pr-end { grid-row: 2; }
body.kb .qs-tally { display: inline-flex; gap: var(--s-3); white-space: nowrap; }
body.kb .qs-tally b { font-weight: 600; color: var(--ink); }
body.kb .qs-round.is-produce .qs-scroll { display: flex; flex-direction: column; }
body.kb .qs-round.is-produce .qs-stage { flex: 1 0 auto; display: flex; flex-direction: column; align-items: stretch; text-align: start; gap: var(--s-2); padding: var(--s-1) 0 0; }
body.kb .qs-round.is-produce .qs-produce { display: contents; }
body.kb .qs-round.is-produce .qs-level .wp-meta { justify-content: flex-start; }
body.kb .qs-round.is-produce .qs-prompt { font-size: 22px; line-height: 1.25; --kb-lines: 3; }
body.kb .qs-round.is-produce .qs-panel { order: 1; max-width: none; }
body.kb .qs-round.is-produce .qs-produce > .reveal-answer { order: 2; }
body.kb .qs-round.is-produce .qs-typo { margin-inline-start: -12px; }
body.kb .qs-round.is-produce .qs-answer { order: 3; position: sticky; bottom: 0; z-index: 1; margin-top: auto; padding-top: var(--s-2); background: var(--canvas); }
body.kb .qs-round.is-produce .qs-skip { display: none; }
body.kb .qs-round.is-produce .qs-actions { display: none; }
body.kb .qs-round.is-produce .qs-kbrow { display: flex; align-items: center; max-width: 640px; width: 100%; margin: 0 auto; padding: 4px 0 6px; background: var(--canvas); }
body.kb .qs-kbrow .btn { min-height: var(--tap); }
body.kb .qs-kbrow .btn-quiet { padding: 0 12px; }
body.kb .qs-kbrow .btn[hidden] { display: none; }

/* Check by typing (shared/typecheck.js) with the keyboard up: the panel is the card's last row, over the keyboard;
   the answer opens above the field, the buttons are one row with Check at the end, and the round's own action row
   waits (AUDIT R3: the field was below the fold of a 741 px card) */
body.kb .sim-card { gap: var(--s-3); }
body.kb .pr-card > .pr-typecheck { order: 4; position: sticky; bottom: 0; z-index: 1; margin-top: auto; padding: var(--s-2) 0 6px; background: var(--canvas); }
body.kb .pr-typecheck > .caption { display: none; }
body.kb .pr-typecheck > .pr-fb { order: 1; padding-top: 0; }
body.kb .pr-typecheck > .answer { order: 2; }
body.kb .pr-typecheck > .pr-typecheck-actions { order: 3; flex-wrap: nowrap; }
body.kb .pr-typecheck-actions > .btn-primary { order: 3; flex: 1; }
body.kb .pr-typecheck-actions .btn[hidden] { display: none; }
body.kb .pr-round:has(.pr-typecheck) > .pr-actions { display: none; }
body.kb .pr-typecheck > .pr-fb:empty { display: none; }
body.kb .pr-typecheck-actions .btn-quiet { padding: 0 12px; }

/* Build an email and Write it yourself with the keyboard up: the email folds to "3 of 7 lines", the card's buttons
   and the free text's word count, clock and Correct sit on the keyboard (styles/app.css .kb-dock) */
.wr-prog { display: none; margin-inline-start: var(--s-2); color: var(--ink-3); font-weight: 400; }
body.kb .wr-prog { display: inline; }
body.kb .wr-letterbox { padding: var(--s-2) var(--s-4); }
body.kb .wr-letterbox > .label { margin-bottom: 0; }
body.kb .wr-letterbox > .wr-letter { display: none; }
body.kb .wr-build .wr-card { scroll-margin-bottom: 64px; }
body.kb .wr-kbbar .wr-kbcount { flex: 1; }
body.kb .wr-kbbar .btn-primary { flex: none; padding: 0 var(--s-5); }
body.kb .wr-freepage .wr-free { min-height: 140px; max-height: calc(var(--vv-h, 100dvh) - 132px); }
body.kb .wr-freepage { padding-bottom: 64px; }
body.kb .pr-typecheck > .answer { margin-top: 0; }
