/* Mobile-first, no framework. Dark by default - this gets used in a car at night. */

:root {
  --bg: #12151a;
  --surface: #1b1f26;
  --surface-2: #232833;
  --line: #2e3542;
  --text: #eef1f6;
  --muted: #98a2b3;
  --accent: #4c8dff;
  --accent-ink: #ffffff;
  --done: #35c86b;
  --warn: #f0a742;
  --danger: #ff6b6b;
  --radius: 12px;
  --tap: 48px;
}

* {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  padding: 0 0 env(safe-area-inset-bottom);
  background: var(--bg);
  color: var(--text);
  font: 16px/1.45 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  min-height: 100vh;
}

/* ------------------------------------------------------------------ layout */

.topbar {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: calc(10px + env(safe-area-inset-top)) 16px 10px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

.topbar h1 {
  flex: 1;
  margin: 0;
  font-size: 17px;
  font-weight: 600;
}

.wrap {
  max-width: 720px;
  margin: 0 auto;
  padding: 16px;
}

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px;
  margin-bottom: 16px;
}

h2 {
  font-size: 16px;
  margin: 0 0 12px;
}

p {
  margin: 0 0 12px;
}

.muted {
  color: var(--muted);
  font-size: 14px;
}

/* Secondary text one step down from .muted. Declared after it so `class="muted small"`
   resolves to the smaller size (equal specificity, later wins). */
.small {
  font-size: 12px;
}

.center {
  text-align: center;
}

/* ------------------------------------------------------------------- forms */

label {
  display: block;
  font-size: 13px;
  color: var(--muted);
  margin: 12px 0 4px;
}

input[type='text'],
input[type='password'] {
  width: 100%;
  min-height: var(--tap);
  padding: 10px 12px;
  font-size: 16px; /* 16px stops iOS from zooming the form */
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 10px;
}

input:focus-visible,
button:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

button {
  min-height: var(--tap);
  padding: 12px 16px;
  font: inherit;
  font-weight: 600;
  color: var(--accent-ink);
  background: var(--accent);
  border: 0;
  border-radius: 10px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

button[disabled] {
  opacity: 0.55;
  cursor: default;
}

button.block {
  width: 100%;
  margin-top: 16px;
}

button.ghost {
  color: var(--text);
  background: transparent;
  border: 1px solid var(--line);
}

button.small {
  min-height: 36px;
  padding: 7px 12px;
  font-size: 14px;
}

button.danger {
  background: var(--danger);
}

/* Destructive but secondary (per-level "Delete", "Delete all downloads"): a red-outlined
   ghost rather than a solid red slab, so a screen listing one per level doesn't read as a
   wall of alarm. Declared after both .ghost and .danger so it wins for either order. */
button.ghost.danger {
  color: var(--danger);
  background: transparent;
  border: 1px solid rgba(255, 107, 107, 0.5);
}

button.ok {
  background: var(--done);
  color: #06240f;
}

.row {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
}

/* -------------------------------------------------------------- tabs/pills */

.tabs {
  display: flex;
  gap: 8px;
  margin-bottom: 16px;
}

.tab {
  flex: 1;
  min-height: 42px;
  padding: 10px;
  font-weight: 600;
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 999px;
}

.tab[aria-selected='true'] {
  color: var(--accent-ink);
  background: var(--accent);
  border-color: var(--accent);
}

/* ------------------------------------------------------------- episode list */

.level {
  margin-bottom: 12px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}

.level > summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 16px;
  min-height: var(--tap);
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}

.level > summary::-webkit-details-marker {
  display: none;
}

.level > summary .chev {
  color: var(--muted);
  transition: transform 0.15s ease;
}

.level[open] > summary .chev {
  transform: rotate(90deg);
}

.level > summary .count {
  margin-left: auto;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}

.level > summary .level-warn {
  font-size: 12px;
  font-weight: 600;
  color: var(--warn);
  white-space: nowrap;
}

.level.complete > summary .count {
  color: var(--done);
}

.bar {
  height: 3px;
  background: var(--surface-2);
}

.bar > span {
  display: block;
  height: 100%;
  background: var(--accent);
}

.level.complete .bar > span {
  background: var(--done);
}

.episodes {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Each row is now a flex pairing of the big "open the player" button (.episode) and a
   narrow sibling actions column (.episode-actions) - two SIBLINGS, deliberately, rather
   than nesting the quick-mark/menu buttons inside .episode itself: nested <button>s are
   invalid HTML and would make the actions' clicks bubble into the row's own navigate
   handler. The row divider moves here (off .episode) so it still spans the whole row
   including the actions column. */
.episodes li.episode-row {
  display: flex;
  align-items: stretch;
  border-top: 1px solid var(--line);
}

.episode {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: 1 1 auto;
  min-width: 0;
  padding: 12px 16px;
  min-height: 56px;
  text-align: left;
  color: var(--text);
  background: transparent;
  border: 0;
  border-radius: 0;
  font-weight: 400;
}

.episode .num {
  flex: none;
  width: 34px;
  font-variant-numeric: tabular-nums;
  font-size: 13px;
  color: var(--muted);
}

.episode .body {
  flex: 1;
  min-width: 0;
}

.episode .title {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.episode .sub {
  display: block;
  font-size: 12px;
  color: var(--muted);
}

.episode .mark {
  flex: none;
  width: 22px;
  text-align: center;
  font-size: 15px;
}

.episode.done .title {
  color: var(--muted);
}

.episode.done .mark {
  color: var(--done);
}

.episode.resuming {
  background: rgba(76, 141, 255, 0.09);
}

.episode.resuming .sub {
  color: var(--accent);
}

.episode.next-up {
  box-shadow: inset 3px 0 0 var(--accent);
}

/* Bulk-mark quick action + "complete through here" row menu (user-requested feature,
   beyond SPEC.md): a small mark-complete/mark-incomplete toggle plus a menu trigger that
   don't navigate into the player. */
.episode-actions {
  position: relative;
  display: flex;
  align-items: center;
  flex: none;
  gap: 2px;
  padding: 0 6px;
}

.episode-actions button {
  flex: none;
  width: 36px;
  height: 36px;
  padding: 0;
  font-size: 16px;
  line-height: 1;
  color: var(--muted);
  background: transparent;
  border: 0;
  border-radius: 8px;
}

.episode-actions button:active {
  background: var(--surface-2);
}

.row-quick {
  color: var(--done);
}

.row-quick.undo {
  color: var(--muted);
}

.row-menu {
  position: absolute;
  top: 100%;
  right: 6px;
  z-index: 5;
  min-width: 190px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  overflow: hidden;
}

.row-menu[hidden] {
  display: none;
}

.row-menu-item {
  display: block;
  width: 100%;
  padding: 12px 14px;
  text-align: left;
  font-size: 14px;
  color: var(--text);
  background: none;
  border: 0;
  border-radius: 0;
}

.row-menu-item:active {
  background: var(--surface);
}

/* ----------------------------------------------------------------- notices */

.notice {
  padding: 10px 12px;
  margin-bottom: 12px;
  font-size: 14px;
  border-radius: 10px;
  background: var(--surface-2);
  border: 1px solid var(--line);
}

.notice.error {
  color: #ffd9d9;
  background: rgba(255, 107, 107, 0.15);
  border-color: rgba(255, 107, 107, 0.4);
}

.notice.ok {
  color: #d6ffe6;
  background: rgba(53, 200, 107, 0.14);
  border-color: rgba(53, 200, 107, 0.4);
}

.notice[hidden] {
  display: none;
}

/* ------------------------------------------------------------------- admin */

.user {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 12px 0;
  border-top: 1px solid var(--line);
}

.user:first-child {
  border-top: 0;
}

.user .who {
  flex: 1;
  min-width: 140px;
}

.user .who b {
  font-weight: 600;
}

.pill {
  display: inline-block;
  padding: 2px 8px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--muted);
}

.pill.approved {
  color: #d6ffe6;
  background: rgba(53, 200, 107, 0.2);
}

.pill.pending {
  color: #ffeccd;
  background: rgba(240, 167, 66, 0.2);
}

.pill.denied {
  color: #ffd9d9;
  background: rgba(255, 107, 107, 0.2);
}

.pill.admin {
  color: #dbe6ff;
  background: rgba(76, 141, 255, 0.25);
}

a {
  color: var(--accent);
}

/* --------------------------------------------------------------- app nav bar */

.appnav {
  display: flex;
  gap: 6px;
  align-items: center;
  padding: 8px 16px;
  overflow-x: auto;
  background: var(--surface-2);
  border-bottom: 1px solid var(--line);
}

.appnav[hidden] {
  display: none;
}

.navlink {
  flex: none;
  padding: 6px 12px;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  text-decoration: none;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 999px;
  white-space: nowrap;
}

.navlink.active {
  color: var(--accent-ink);
  background: var(--accent);
  border-color: var(--accent);
}

/* --------------------------------------------------------------- install hint */

.install-hint {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  font-size: 13px;
  color: var(--text);
  background: var(--surface-2);
  border-bottom: 1px solid var(--line);
}

.install-hint p {
  flex: 1;
  margin: 0;
}

.install-hint-dismiss {
  flex: none;
  min-height: 32px;
  width: 32px;
  padding: 0;
  font-size: 14px;
  line-height: 1;
  color: var(--muted);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 50%;
}

/* ------------------------------------------------------------------- player */

.player-card {
  text-align: center;
}

#lesson-sub {
  margin: 0 0 12px;
}

audio {
  display: none; /* controlled entirely by the custom transport below */
}

.scrub-range {
  width: 100%;
  height: var(--tap);
  margin: 0;
  accent-color: var(--accent);
  background: transparent;
}

.time-row {
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  margin-top: -6px;
}

.transport {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 20px;
  margin: 12px 0 16px;
}

.transport-btn {
  min-height: 0;
  width: 60px;
  height: 60px;
  padding: 0;
  border-radius: 50%;
  font-size: 14px;
  font-weight: 700;
  background: var(--surface-2);
  color: var(--text);
  border: 1px solid var(--line);
}

.transport-btn.play {
  width: 88px;
  height: 88px;
  font-size: 30px;
  background: var(--accent);
  color: var(--accent-ink);
  border: 0;
}

.secondary-controls {
  justify-content: center;
  margin-bottom: 20px;
}

.auto-advance-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  font-size: 13px;
  color: var(--muted);
}

.auto-advance-toggle input {
  width: 20px;
  height: 20px;
}

.star-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

.star-btn {
  width: 88px;
  height: 88px;
  border-radius: 50%;
  font-size: 42px;
  line-height: 1;
  background: var(--surface-2);
  border: 2px solid var(--warn);
  box-shadow: none;
  transition: transform 0.12s ease;
}

.star-btn.pop {
  animation: star-pop 0.35s ease;
}

@keyframes star-pop {
  0% {
    transform: scale(1);
  }
  40% {
    transform: scale(1.25);
  }
  100% {
    transform: scale(1);
  }
}

.star-hint {
  min-height: 1.2em;
  margin: 0;
}

textarea {
  width: 100%;
  min-height: 110px;
  padding: 10px 12px;
  font: inherit;
  font-size: 16px; /* stops iOS from zooming the field on focus */
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  resize: vertical;
}

/* ------------------------------------------------- offline / downloads (milestone 4) */

/* Sits above the topbar on every page (public/js/api.js#setOffline). Amber rather than
   red: being offline is a normal state for this app, not an error. */
.offline-bar {
  padding: calc(6px + env(safe-area-inset-top)) 16px 6px;
  font-size: 13px;
  font-weight: 600;
  text-align: center;
  color: #ffeccd;
  background: rgba(240, 167, 66, 0.22);
  border-bottom: 1px solid rgba(240, 167, 66, 0.45);
}

.offline-bar[hidden] {
  display: none;
}

/* When the offline bar is showing it owns the safe-area inset (it is the first element in
   the body), so the sticky topbar directly below it must not add its own on top. */
.offline-bar:not([hidden]) + .topbar {
  padding-top: 10px;
}

/* "Available offline" pill, and the auto-cache counter on the downloads screen. */
.pill.offline-pill {
  color: #dbe6ff;
  background: rgba(76, 141, 255, 0.22);
  text-transform: none;
  letter-spacing: 0;
  font-size: 12px;
}

.pill.auto-pill {
  text-transform: none;
  letter-spacing: 0;
  white-space: nowrap;
}

/* Eviction/interrupted-download flag on the Downloads screen (milestone 7). */
.pill.warn-pill {
  color: #2a1a03;
  background: var(--warn);
  text-transform: none;
  letter-spacing: 0;
  white-space: nowrap;
}

/* --- library: per-episode badge + per-level download row --- */

/* The ⤓ marker on a cached episode. Same fixed width as .mark so titles stay aligned
   whether or not a lesson is stored. */
.episode .offline-mark {
  flex: none;
  width: 18px;
  text-align: center;
  font-size: 13px;
  color: var(--muted);
}

/* `.offline-ready` is the row-level hook library.js toggles alongside the badge, so a
   stored lesson reads as stored from the row itself, not just the glyph. */
.episode.offline-ready .offline-mark {
  color: var(--accent);
}

.episode .offline-mark[hidden] {
  /* Keeps the column, loses the glyph - the row must not reflow as downloads land. */
  display: block;
  visibility: hidden;
}

.level-download {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 10px 16px;
  background: var(--surface-2);
  border-top: 1px solid var(--line);
}

.level-download button[hidden] {
  display: none;
}

.dl-status {
  flex: 1;
  min-width: 0;
  font-variant-numeric: tabular-nums;
}

/* --- player: offline badge + save button --- */

.offline-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 36px;
  margin-bottom: 4px;
}

.offline-row [hidden] {
  display: none;
}

/* The "re-download needed" state carries an inline action button. */
.notice button {
  margin-left: 8px;
  vertical-align: middle;
}

/* --- downloads screen --- */

.storage-total {
  margin: 0 0 8px;
  font-size: 20px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.storage-bar {
  height: 10px;
  margin-bottom: 10px;
  border-radius: 999px;
  overflow: hidden;
}

.storage-bar > span {
  border-radius: 999px;
  transition: width 0.2s ease;
}

.download-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 0;
  border-top: 1px solid var(--line);
}

.download-row:first-of-type {
  border-top: 0;
}

.download-label {
  display: flex;
  flex: 1;
  min-width: 0;
  flex-direction: column;
  gap: 2px;
}

.download-label b {
  font-weight: 600;
}

.download-row button {
  flex: none;
}

/* The redownload/delete pair (milestone 7). flex-shrink:0 so a narrow viewport wraps the
   buttons onto their own line under the label instead of squeezing both into the leftover
   width beside it. */
.download-row-actions {
  flex-shrink: 0;
}

/* ------------------------------------------------------- vocab editor (milestone 5) */

select {
  width: 100%;
  min-height: var(--tap);
  padding: 10px 12px;
  font-size: 16px; /* stops iOS from zooming the field on focus */
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 10px;
}

input[type='file'] {
  width: 100%;
  margin: 8px 0;
  font-size: 14px;
  color: var(--muted);
}

.vocab-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 0;
  border-top: 1px solid var(--line);
}

.vocab-row:first-child {
  border-top: 0;
}

.vocab-row-body {
  flex: 1;
  min-width: 0;
}

.vocab-row-main {
  word-break: break-word;
}

.vocab-row-actions {
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: none;
}

.vocab-row-editing {
  flex-direction: column;
  align-items: stretch;
}

.vocab-row-fields {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 8px;
}

.vocab-row-fields input {
  width: 100%;
  min-height: 40px;
  padding: 8px 10px;
  font-size: 16px;
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 8px;
}

.vocab-row-editing .vocab-row-actions {
  flex-direction: row;
}

.vocab-form {
  display: flex;
  flex-direction: column;
}

.vocab-form input {
  margin-bottom: 4px;
}

/* ------------------------------------------------- review + stats (milestone 6) */
/* Flashcards are used "outside the car - visual, touch-first ... at rest" (SPEC.md
   section 10), so the card is big and the two grade buttons are deliberately oversized
   and thumb-reachable rather than sized like the rest of the UI's controls. */

.nav-badge {
  display: inline-block;
  min-width: 18px;
  margin-left: 6px;
  padding: 0 5px;
  font-size: 11px;
  font-weight: 700;
  line-height: 18px;
  text-align: center;
  color: var(--accent-ink);
  background: var(--accent);
  border-radius: 9px;
}

.review-card-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}

.review-card-head h2 {
  flex: 1;
  margin: 0;
}

.pill.due-pill {
  background: rgba(76, 141, 255, 0.16);
  color: var(--accent);
}

.pill.star-pill {
  background: rgba(240, 167, 66, 0.16);
  color: var(--warn);
}

.review-prompt a {
  margin-left: 6px;
}

.review-audio-toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: var(--tap);
  margin: 8px 0;
  font-size: 15px;
  color: var(--text);
}

.review-audio-toggle input {
  width: 22px;
  height: 22px;
  margin: 0;
  accent-color: var(--accent);
}

/* --- the timer bar: "progress bar showing time remaining" --------------------- */

.timer {
  margin-bottom: 12px;
}

.bar.timer-bar {
  height: 8px;
}

.timer-bar > span {
  background: var(--accent);
}

.timer-row {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  margin-top: 6px;
}

/* --- the card ---------------------------------------------------------------- */

.flashcard {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 260px;
  padding: 20px 16px;
  text-align: center;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: border-color 0.15s ease, background 0.15s ease;
}

.flashcard.flipped {
  border-color: var(--accent);
  background: var(--surface-2);
}

.flashcard-head {
  display: flex;
  align-self: stretch;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 16px;
}

.flashcard-prompt {
  margin: 0 0 8px;
  font-size: 28px;
  font-weight: 600;
  line-height: 1.25;
}

.flashcard-answer {
  margin: 12px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--line);
  align-self: stretch;
  font-size: 22px;
  color: var(--done);
}

/* The example sentence from the transcript - "isolated words retain poorly"
   (SPEC.md section 10), so it is present but visually secondary to the answer. */
.flashcard-example {
  margin: 10px 0 0;
  font-size: 15px;
  font-style: italic;
  color: var(--muted);
}

.flip-hint {
  margin: 16px 0 0;
}

.flashcard-answer[hidden],
.flashcard-example[hidden],
.flip-hint[hidden] {
  display: none;
}

/* --- grading ----------------------------------------------------------------- */

.grade-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-bottom: 16px;
}

.grade-row[hidden] {
  display: none;
}

.grade-btn {
  min-height: 64px;
  padding: 12px;
  font-size: 17px;
  font-weight: 600;
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.grade-btn.got {
  color: #08240f;
  background: var(--done);
  border-color: var(--done);
}

.grade-btn.missed {
  color: #2a0b0b;
  background: var(--danger);
  border-color: var(--danger);
}

.session-controls {
  flex-wrap: wrap;
}

.session-controls [hidden] {
  display: none;
}

/* --- stats ------------------------------------------------------------------- */

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 10px;
  margin-bottom: 12px;
}

.stat-tile {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 12px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 10px;
}

.stat-value {
  font-size: 24px;
  font-weight: 700;
  line-height: 1.1;
}

.stat-label {
  font-size: 12px;
  color: var(--muted);
}

.stat-sub {
  font-size: 11px;
  color: var(--muted);
  opacity: 0.8;
}

.retention-row,
.level-stat {
  margin-bottom: 14px;
}

.retention-head {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 6px;
  font-size: 14px;
}

.retention-row p {
  margin: 6px 0 0;
}

.weakest {
  margin: 0;
  padding-left: 22px;
}

.weakest li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 0;
  border-top: 1px solid var(--line);
}

.weakest li:first-child {
  border-top: 0;
}

/* flex:1 + min-width:0 (milestone 7): without these, a long word/translation pair pushed
   the row past the card's width instead of wrapping - the one horizontal-overflow bug
   found while checking iPhone-SE-width (375px) layout. */
.weak-word {
  display: flex;
  flex: 1;
  min-width: 0;
  flex-direction: column;
  gap: 2px;
  overflow-wrap: break-word;
}

.weak-meta {
  flex: none;
  white-space: nowrap;
}

/* ------------------------------------------------------- conversation practice (M10) */

.practice-head h2 {
  margin-bottom: 2px;
}

.practice-position {
  margin: 10px 0 4px;
  font-weight: 600;
}

.practice-pickers {
  gap: 12px;
}

.practice-picker {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  font-size: 14px;
  color: var(--text);
}

.chat-log {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 12px 0;
}

/* Tutor left, learner right. max-width + overflow-wrap so a long unbroken word (or a pasted
   URL) wraps inside the bubble instead of widening the page at iPhone-SE width. */
.chat-bubble {
  max-width: 85%;
  padding: 10px 12px;
  border-radius: 14px;
  line-height: 1.4;
  overflow-wrap: anywhere;
}

.chat-bubble.tutor {
  align-self: flex-start;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-bottom-left-radius: 4px;
}

.chat-bubble.learner {
  align-self: flex-end;
  background: var(--accent);
  color: var(--accent-ink);
  border-bottom-right-radius: 4px;
}

/* The prompt's correction format, *(Tip: …)* - muted so it reads as an aside, not the reply. */
.chat-tip {
  display: block;
  margin: 2px 0 4px;
  font-size: 14px;
  color: var(--muted);
}

.chat-typing {
  margin: 0 0 8px;
}

.chat-compose {
  display: flex;
  gap: 8px;
  align-items: flex-end;
}

.chat-compose textarea {
  flex: 1;
  min-width: 0;
  min-height: var(--tap);
  padding: 10px 12px;
  font: inherit;
  font-size: 16px; /* 16px stops iOS from zooming on focus */
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  resize: vertical;
}

.meaning-errors li,
.new-words li {
  padding: 8px 0;
  border-top: 1px solid var(--line);
  list-style: none;
}

.meaning-errors,
.new-words {
  padding: 0;
}

.new-word {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 0;
  font-size: 15px;
  color: var(--text);
}

.practice-picker select {
  width: auto;
  min-width: 72px;
}

/* ------------------------------------------------------- voice practice (M11) */

/* The hands-free panel: one big button (Start / Pause / Skip), a live mic level so the learner
   can SEE the microphone is hearing them, and a one-line status. Sits where the composer was;
   the composer itself folds away under "Type instead". */
.voice-panel {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin: 8px 0 4px;
}

.voice-btn {
  width: 100%;
  max-width: 320px;
  min-height: 64px;
  border-radius: 32px;
  font-size: 18px;
  font-weight: 600;
}

.voice-btn[data-state='listening'],
.voice-btn[data-state='recording'] {
  background: var(--done);
}

.voice-btn[data-state='speaking'] {
  background: var(--surface-2);
  color: var(--text);
  border: 1px solid var(--line);
}

.voice-meter {
  width: 100%;
  max-width: 320px;
  height: 6px;
  border-radius: 3px;
  background: var(--surface-2);
  overflow: hidden;
}

.voice-level {
  width: 0;
  height: 100%;
  background: var(--done);
  transition: width 60ms linear;
}

.voice-status {
  margin: 0;
  min-height: 1.4em;
  text-align: center;
}

.type-toggle {
  display: block;
  margin: 0 auto 8px;
}

/* Replay control on a tutor bubble whose speech is still cached. */
.chat-replay {
  display: block;
  margin-top: 6px;
  min-height: 32px;
  padding: 2px 10px;
  font-size: 13px;
}

/* These set `display`, which would otherwise beat the `hidden` attribute the page toggles. */
.voice-panel[hidden],
.type-toggle[hidden],
.chat-compose[hidden] {
  display: none;
}
