:root {
  --bg: #f5f6fa;
  --surface: #ffffff;
  --text: #1c1e26;
  --muted: #6b7280;
  --border: #e2e4ea;
  --primary: #3b5bdb;
  --primary-text: #ffffff;
  --secondary: #eef0f6;
  --secondary-text: #1c1e26;
  --danger: #e03131;
  --good: #2f9e44;
  --warn: #f08c00;
  --state-new: #9096a5;
  --state-learning: #f08c00;
  --state-incorrect: #e03131;
  --state-memorized: #2f9e44;
  --shadow: 0 1px 3px rgba(0,0,0,0.08), 0 1px 2px rgba(0,0,0,0.06);
  /* Almost every font-size and quite a few paddings in this file are `rem`,
     so this one number scales the whole app's text and much of its spacing
     together - bumped up from the 16px browser default because on a phone
     (this app's primary use case) too much of the UI reads as small even
     though it technically fits. Pixel-sized touch targets (small round
     icon buttons especially) don't scale with this and are bumped
     individually below instead. */
  font-size: 18px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #14161c;
    --surface: #1d2028;
    --text: #e8e9ee;
    --muted: #9096a5;
    --border: #2c303c;
    --secondary: #2a2e3a;
    --secondary-text: #e8e9ee;
    --shadow: 0 1px 3px rgba(0,0,0,0.4), 0 1px 2px rgba(0,0,0,0.3);
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang TC", "Noto Sans TC", Roboto, Helvetica, Arial, sans-serif;
  padding-bottom: 40px;
}

.topbar {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  padding: 16px max(16px, calc((100% - 720px) / 2));
  position: sticky;
  top: 0;
  z-index: 10;
}

.topbar h1 {
  margin: 0 0 12px 0;
  font-size: 1.25rem;
}

.muted { color: var(--muted); font-weight: 400; }

.tabs {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.tab-btn {
  background: var(--secondary);
  color: var(--secondary-text);
  border: none;
  border-radius: 999px;
  padding: 11px 18px;
  font-size: 0.95rem;
  cursor: pointer;
}

.tab-btn.active {
  background: var(--primary);
  color: var(--primary-text);
}

#app {
  max-width: 720px;
  margin: 0 auto;
  padding: 20px 16px;
}

.view { display: none; }
.view.active { display: block; }

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 24px;
  box-shadow: var(--shadow);
}

.card + .card { margin-top: 16px; }

.card h2 {
  font-size: 1rem;
  margin: 24px 0 10px 0;
  color: var(--muted);
}
.card h2:first-child { margin-top: 0; }

.level-picker {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.level-chip {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--secondary);
  border-radius: 10px;
  padding: 13px 18px;
  cursor: pointer;
  font-weight: 600;
}

.level-chip input { accent-color: var(--primary); width: 20px; height: 20px; }

.mode-picker {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.mode-chip {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 8px;
  background: var(--secondary);
  border-radius: 10px;
  padding: 10px 14px;
  cursor: pointer;
  border: 2px solid transparent;
}

.mode-chip:has(input:checked), .mode-chip.selected { border-color: var(--primary); }

.mode-chip input { accent-color: var(--primary); width: 20px; height: 20px; }

.mode-chip span { font-weight: 600; }

.mode-chip small {
  flex-basis: 100%;
  color: var(--muted);
  font-size: 0.85rem;
  line-height: 1.4;
}

.filter-chip {
  background: var(--secondary);
  color: var(--secondary-text);
  border: none;
  border-radius: 999px;
  padding: 10px 16px;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
}

.filter-chip.active { background: var(--primary); color: var(--primary-text); }

.hint {
  color: var(--muted);
  font-size: 0.85rem;
  line-height: 1.5;
}

.hint.danger-text { color: var(--danger); }

.row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
  flex-wrap: wrap;
}

.row label {
  min-width: 90px;
  font-size: 0.9rem;
  color: var(--muted);
}

select, input[type="text"] {
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 11px 14px;
  font-size: 1rem;
}

input[type="range"] { accent-color: var(--primary); flex: 1; max-width: 200px; min-height: 24px; }

.btn {
  border: none;
  border-radius: 10px;
  padding: 14px 22px;
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
}

.btn.primary { background: var(--primary); color: var(--primary-text); }
.btn.secondary { background: var(--secondary); color: var(--secondary-text); }
.btn.danger { background: transparent; color: var(--danger); border: 1px solid var(--danger); }

.actions { margin-top: 16px; }

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

.progress-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}

.progress-bar {
  flex: 1;
  height: 8px;
  background: var(--secondary);
  border-radius: 999px;
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  background: var(--primary);
  width: 0%;
  transition: width 0.25s ease;
}

#test-progress-text {
  font-size: 0.8rem;
  color: var(--muted);
  white-space: nowrap;
}

.level-badge {
  display: inline-block;
  background: var(--secondary);
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 700;
  padding: 4px 10px;
  border-radius: 999px;
  margin-bottom: 20px;
}

.play-btn {
  display: block;
  margin: 0 auto 12px auto;
  width: 88px;
  height: 88px;
  border-radius: 50%;
  border: none;
  background: var(--primary);
  color: var(--primary-text);
  font-size: 2rem;
  cursor: pointer;
  box-shadow: var(--shadow);
}

.play-btn:active { transform: scale(0.96); }

#test-form {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 16px;
}

#test-input {
  width: 100%;
  max-width: 320px;
  text-align: center;
  font-size: 1.4rem;
  letter-spacing: 1px;
  padding: 14px;
}

.feedback {
  margin-top: 20px;
  padding: 14px;
  border-radius: 10px;
  font-size: 1.1rem;
  font-weight: 600;
}
.feedback.correct { background: rgba(47,158,68,0.12); color: var(--good); }
.feedback.wrong { background: rgba(224,49,49,0.1); color: var(--danger); }
.feedback .answer-word { font-size: 1.3rem; }

.hidden { display: none !important; }

.zh-meaning {
  margin-top: 6px;
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--text);
}

.speed-note {
  margin-top: 10px;
  font-size: 0.85rem;
}
.speed-note.faster { color: var(--good); }
.speed-note.slower { color: var(--warn); }

.answer-diff {
  margin-top: 10px;
  font-size: 0.95rem;
  font-weight: 400;
}

.answer-state {
  margin-top: 10px;
}

.summary { margin-top: 20px; text-align: left; }
.summary h2 { color: var(--text); }

.missed-list {
  list-style: none;
  padding: 0;
  margin: 12px 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 8px;
}

.missed-list li {
  background: var(--secondary);
  border-radius: 8px;
  padding: 8px 10px;
  font-size: 0.9rem;
}

.word-chip-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 8px;
  margin: 12px 0;
}

.word-chip {
  background: var(--secondary);
  border-radius: 8px;
  overflow: hidden;
}

.word-chip-btn {
  width: 100%;
  text-align: left;
  background: transparent;
  border: none;
  color: var(--secondary-text);
  font-size: 0.9rem;
  font-weight: 600;
  padding: 8px 10px;
  cursor: pointer;
}

.word-chip-zh {
  padding: 0 10px 10px 10px;
  font-size: 0.85rem;
  font-weight: 400;
  line-height: 1.5;
  color: var(--text);
}

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

.stat-box {
  background: var(--secondary);
  border-radius: 12px;
  padding: 14px;
  text-align: center;
}

.stat-box .num {
  font-size: 1.6rem;
  font-weight: 700;
  display: block;
}

.stat-box .label {
  font-size: 0.8rem;
  color: var(--muted);
}

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

.level-stat-row .level-stat-head {
  display: flex;
  justify-content: space-between;
  font-size: 0.85rem;
  color: var(--muted);
  margin-bottom: 4px;
}

.level-stat-bar {
  height: 10px;
  border-radius: 999px;
  background: var(--secondary);
  overflow: hidden;
  display: flex;
}

.level-stat-bar .seg { height: 100%; }
.seg-new { background: var(--state-new); }
.seg-learning { background: var(--state-learning); }
.seg-incorrect { background: var(--state-incorrect); }
.seg-memorized { background: var(--state-memorized); }

.state-badge {
  display: inline-block;
  font-size: 0.75rem;
  font-weight: 700;
  padding: 3px 9px;
  border-radius: 999px;
  color: #fff;
  white-space: nowrap;
}
.state-badge.new { background: var(--state-new); }
.state-badge.learning { background: var(--state-learning); }
.state-badge.incorrect { background: var(--state-incorrect); }
.state-badge.memorized { background: var(--state-memorized); }

.word-table-wrap {
  overflow-x: auto;
  margin-top: 10px;
  border: 1px solid var(--border);
  border-radius: 10px;
}

.word-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
  white-space: nowrap;
}

.word-table th, .word-table td {
  padding: 8px 12px;
  text-align: left;
  border-bottom: 1px solid var(--border);
}

.word-table th {
  color: var(--muted);
  font-weight: 600;
  background: var(--secondary);
  position: sticky;
  top: 0;
}

.word-table tbody tr:last-child td { border-bottom: none; }

.word-cell { font-weight: 600; }

.row-play-btn {
  border: none;
  background: var(--secondary);
  color: var(--secondary-text);
  border-radius: 999px;
  width: 36px;
  height: 36px;
  line-height: 1;
  font-size: 0.95rem;
  cursor: pointer;
  vertical-align: middle;
  margin-right: 6px;
}

.row-word-toggle {
  cursor: pointer;
  text-decoration: underline dotted;
  text-underline-offset: 3px;
}

.row-zh {
  white-space: normal;
  max-width: 280px;
  font-weight: 400;
  font-size: 0.85rem;
  color: var(--text);
  margin-top: 4px;
  line-height: 1.5;
}

.diff-miss {
  background: rgba(224, 49, 49, 0.15);
  color: var(--danger);
  border-radius: 3px;
  padding: 0 1px;
}

.word-card-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 12px 0;
}

.word-card {
  background: var(--secondary);
  border-radius: 10px;
  padding: 10px 12px;
}

/* Word/pos/level (text, wraps naturally if a word is long) and the action
   buttons (play/dict/mark) are two DELIBERATE, separately-styled rows,
   not one row left to wrap wherever it runs out of space - three roughly
   40px touch targets plus a word plus two badges never reliably fit on one
   line at phone width, and letting flexbox wrap them by accident stranded
   whichever button ran out of room on its own near-empty line. */
.word-card-main {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.word-card-actions {
  display: flex;
  gap: 8px;
  margin-top: 6px;
}

.word-card-word {
  font-weight: 700;
  font-size: 1.05rem;
}

.word-card-level {
  display: inline-block;
  background: var(--surface);
  color: var(--muted);
  font-size: 0.7rem;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: 999px;
}

.card-play-btn, .card-dict-btn, .card-mark-btn {
  border: none;
  background: var(--surface);
  color: var(--secondary-text);
  border-radius: 999px;
  width: 40px;
  height: 40px;
  line-height: 1;
  font-size: 1.05rem;
  cursor: pointer;
  flex-shrink: 0;
}

.word-card-meta {
  font-size: 0.8rem;
  margin-top: 4px;
}

.word-card-wrong {
  font-size: 0.9rem;
  margin-top: 6px;
}

.pager {
  justify-content: center;
  margin-top: 12px;
  margin-bottom: 0;
}

.pager-btn {
  background: var(--secondary);
  color: var(--secondary-text);
  border: none;
  border-radius: 999px;
  padding: 10px 16px;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
}

.pager-btn:disabled {
  opacity: 0.4;
  cursor: default;
}

.footer {
  text-align: center;
  color: var(--muted);
  font-size: 0.8rem;
  padding: 20px 16px;
}

.btn.small {
  padding: 9px 16px;
  font-size: 0.85rem;
  font-weight: 600;
}

.update-row {
  margin-top: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
}

.update-status {
  font-size: 0.8rem;
}

.update-status.up-to-date { color: var(--good); }
.update-status.updating { color: var(--primary); }
.update-status.error { color: var(--danger); }

.update-toast {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  background: var(--text);
  color: var(--bg);
  padding: 10px 20px;
  border-radius: 999px;
  font-size: 0.85rem;
  font-weight: 600;
  box-shadow: var(--shadow);
  z-index: 100;
}

@media (max-width: 480px) {
  .play-btn { width: 88px; height: 88px; font-size: 1.9rem; }
  .flashcard-word { font-size: 1.7rem; }
}

/* ---------- Review tab: category / view-mode segmented tabs ---------- */

.segmented {
  display: flex;
  gap: 8px;
}

.segmented-btn {
  flex: 1;
  background: var(--secondary);
  color: var(--secondary-text);
  border: 2px solid transparent;
  border-radius: 10px;
  padding: 14px 10px;
  font-size: 0.95rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}

.segmented-btn.active {
  background: var(--primary);
  color: var(--primary-text);
}

/* ---------- Review tab: flashcard swipe view ---------- */

.flashcard-stage {
  display: flex;
  justify-content: center;
  padding: 4px 0 16px 0;
  /* Keeps a card being dragged off-screen (see app.js's swipe handling)
     from visually spilling past this card's own rounded corners. */
  overflow: hidden;
}

.flashcard {
  width: 100%;
  max-width: 360px;
  min-height: 260px;
  background: var(--secondary);
  border-radius: 16px;
  padding: 28px 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 8px;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  touch-action: pan-y;
  position: relative;
  transition: transform 0.25s ease, opacity 0.25s ease;
}

/* Disabled while a finger/pointer is actively dragging the card (see
   app.js's flashcard swipe handling) so it tracks the pointer 1:1 instead
   of lagging behind the transition; re-enabled the instant the drag ends,
   for the snap-back or swipe-away animation. */
.flashcard.dragging {
  transition: none;
}

.flashcard-level {
  position: absolute;
  top: 14px;
  left: 14px;
  background: var(--surface);
  color: var(--muted);
  font-size: 0.7rem;
  font-weight: 700;
  padding: 3px 9px;
  border-radius: 999px;
}

.flashcard-mark-btn {
  position: absolute;
  top: 10px;
  right: 10px;
  border: none;
  background: var(--surface);
  color: var(--muted);
  width: 40px;
  height: 40px;
  border-radius: 50%;
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
}

.flashcard-mark-btn.marked,
.card-mark-btn.marked {
  color: #f0b400;
}

.flashcard-play-btn {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  font-size: 1.7rem;
  margin-bottom: 4px;
  box-shadow: var(--shadow);
}

.flashcard-word {
  font-size: 2rem;
  font-weight: 700;
  letter-spacing: 0.5px;
  word-break: break-word;
}

.flashcard-pos {
  font-size: 0.9rem;
}

.flashcard-reveal {
  margin-top: 6px;
  font-size: 1rem;
  line-height: 1.6;
  color: var(--text);
}

.flashcard-reveal .word-card-wrong {
  margin-top: 10px;
  font-size: 0.9rem;
}

.flashcard-tap-hint {
  margin: 2px 0 0 0;
  font-size: 0.75rem;
}

.flashcard-nav {
  margin-top: 4px;
  display: flex;
  gap: 10px;
}

.flashcard-nav .btn {
  flex: 1;
}

/* ---------- Cross-device sync panel ---------- */

#sync-join-fold {
  margin-top: 4px;
}

#sync-join-fold summary {
  cursor: pointer;
  color: var(--primary);
  font-weight: 600;
  font-size: 0.9rem;
  padding: 6px 0;
  list-style: none;
}

#sync-join-fold summary::-webkit-details-marker { display: none; }
#sync-join-fold summary::before {
  content: "▸";
  display: inline-block;
  margin-right: 6px;
  transition: transform 0.15s ease;
}
#sync-join-fold[open] summary::before { transform: rotate(90deg); }

#sync-join-fold[open] {
  background: var(--bg);
  border-radius: 10px;
  padding: 4px 12px 12px 12px;
  margin-top: 8px;
}

.sync-created-box {
  background: rgba(240, 140, 0, 0.08);
  border: 1px solid var(--warn);
  border-radius: 12px;
  padding: 14px 16px;
  margin: 12px 0;
}

#sync-active-box strong, #sync-created-codes strong {
  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
  font-size: 1.05rem;
  letter-spacing: 1px;
}

#sync-status {
  min-height: 1.2em;
}

/* ---------- Word-type ratio sliders (home screen) ---------- */

.ratio-value {
  display: inline-block;
  min-width: 3ch;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* ---------- Custom confirm dialog (replaces the native confirm()) ---------- */

.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  z-index: 1000;
}

.modal-box {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.25);
  padding: 20px;
  width: 100%;
  max-width: 380px;
  max-height: 80vh;
  overflow-y: auto;
}

#modal-message p {
  margin: 0 0 10px;
  line-height: 1.6;
  white-space: pre-wrap;
}
#modal-message p:last-child { margin-bottom: 0; }

.modal-actions {
  margin-top: 18px;
  justify-content: flex-end;
}

/* ---------- General interaction polish ---------- */

.btn {
  transition: filter 0.15s ease, transform 0.05s ease;
}
.btn:hover:not(:disabled) { filter: brightness(1.08); }
.btn:active:not(:disabled) { transform: scale(0.98); }
.btn:disabled {
  opacity: 0.55;
  cursor: default;
  filter: none;
}

.tab-btn, .filter-chip, .level-chip {
  transition: background-color 0.15s ease, color 0.15s ease;
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

input[type="text"]:focus, input[type="number"]:focus, select:focus {
  border-color: var(--primary);
}

@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.001ms !important; animation-duration: 0.001ms !important; }
}
