:root {
  --bg: #faf9ff;
  --bg-elevated: #ffffff;
  --bg-elevated-2: #f4f1fc;
  --text: #332f4d;
  --text-muted: #918dae;
  --accent: #a78bfa;
  --accent-2: #7dd3fc;
  --accent-text: #4c3aa8;
  --accent-gradient: linear-gradient(135deg, #c4b5fd 0%, #93c5fd 100%);
  --success: #34d399;
  --success-2: #6ee7b7;
  --success-text: #06603f;
  --success-gradient: linear-gradient(135deg, #86efac 0%, #5eead4 100%);
  --danger: #fb7185;
  --danger-2: #fca5a5;
  --danger-text: #9d174d;
  --danger-gradient: linear-gradient(135deg, #fda4af 0%, #fecaca 100%);
  --border: #e9e5f8;
  --shadow: 0 16px 34px rgba(140, 121, 214, 0.16);
  --shadow-sm: 0 4px 16px rgba(140, 121, 214, 0.12);
}

* {
  box-sizing: border-box;
}

html, body {
  height: 100%;
  /* iOS Safari's address/tab bars can shrink the actually-visible area below
     what a plain 100% (≈100vh) assumes; dvh tracks the real visible height.
     Browsers that don't understand it ignore this line and keep 100% above. */
  height: 100dvh;
  margin: 0;
}

body {
  background:
    radial-gradient(900px 620px at 8% -8%, #ede9fe 0%, transparent 55%),
    radial-gradient(900px 620px at 100% 0%, #e0f2fe 0%, transparent 52%),
    radial-gradient(760px 560px at 50% 105%, #fce7f3 0%, transparent 48%),
    var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
  padding-top: env(safe-area-inset-top);
  padding-bottom: env(safe-area-inset-bottom);
  overscroll-behavior-y: contain;
}

.app-header {
  padding: 18px 16px 8px;
  text-align: center;
}

.app-header-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

.app-header h1 {
  margin: 0;
  font-size: 1.6rem;
  font-weight: 400;
  letter-spacing: 0.02em;
  background: linear-gradient(135deg, #8b5cf6 0%, #38bdf8 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.header-refresh-btn {
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
}

.header-refresh-btn svg {
  width: 16px;
  height: 16px;
}

.header-refresh-btn.is-refreshing svg {
  animation: header-refresh-spin 0.8s linear infinite;
}

@keyframes header-refresh-spin {
  to { transform: rotate(360deg); }
}

.app-view {
  flex: 1;
  overflow-y: auto;
  min-height: 0;
}

.pad {
  padding: 16px;
}

.center {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  min-height: 60vh;
  gap: 16px;
}

/* Text-centering only, no vertical centering — used instead of .center on
   the Auto/Quiz/Grammatik start screens. Those three differ quite a bit in
   how much content they have (Auto's extra "Eingabeart" toggle row,
   Grammatik's single dropdown vs. Quiz's two mode buttons), so vertically
   centering each would float its content to a different height and make
   switching between the nav tabs look like everything jumps around. Content
   starting at a fixed top offset instead stays visually stable. */
.center-text {
  text-align: center;
}

.hint {
  color: var(--text-muted);
  font-size: 0.95rem;
}

.app-nav {
  display: flex;
  border-top: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  padding-bottom: env(safe-area-inset-bottom);
}

.nav-btn {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 10px 8px 12px;
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 0.8rem;
  cursor: pointer;
  position: relative;
  transition: color 0.15s ease;
}

.nav-icon {
  width: 24px;
  height: 24px;
  display: inline-flex;
}

.nav-icon svg {
  width: 100%;
  height: 100%;
}

.nav-btn.active {
  color: var(--accent-text);
  font-weight: 700;
}

.nav-btn.active::after {
  content: '';
  position: absolute;
  bottom: 4px;
  left: 50%;
  transform: translateX(-50%);
  width: 26px;
  height: 3px;
  border-radius: 999px;
  background: var(--accent-gradient);
}

.btn {
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 14px 20px;
  font-size: 1rem;
  cursor: pointer;
  color: var(--text);
  background: var(--bg-elevated);
  box-shadow: var(--shadow-sm);
  transition: transform 0.12s ease, box-shadow 0.12s ease, filter 0.12s ease, opacity 0.12s ease;
}

.btn:active {
  transform: scale(0.97);
  box-shadow: none;
}

.btn:disabled {
  opacity: 0.5;
  transform: none;
  cursor: default;
}

.btn-primary {
  background: var(--accent-gradient);
  border-color: transparent;
  color: var(--accent-text);
  font-weight: 700;
  box-shadow: 0 10px 24px rgba(167, 139, 250, 0.35);
}

.btn-secondary {
  background: var(--bg-elevated);
}

.btn-success {
  background: var(--success-gradient);
  border-color: transparent;
  color: var(--success-text);
  font-weight: 700;
  box-shadow: 0 10px 24px rgba(52, 211, 153, 0.32);
}

.btn-danger {
  background: var(--danger-gradient);
  border-color: transparent;
  color: var(--danger-text);
  font-weight: 700;
  box-shadow: 0 10px 24px rgba(251, 113, 133, 0.3);
}

.btn-huge {
  width: 100%;
  min-height: 25vh;
  font-size: 1.6rem;
  border-radius: 26px;
}

/* Used for mid-question buttons (Quiz's "Weiter"/"Prüfen") that sit below
   other content — a blind-tap-sized button there just pushes the next
   question off-screen and forces scrolling, which those buttons don't need
   (unlike Auto mode's rate buttons, meant to be hit without looking). */
.btn-huge.btn-compact {
  min-height: auto;
  padding: 12px 20px;
  font-size: 1.1rem;
  flex-shrink: 0;
}

/* Start buttons on Auto/Quiz/Grammatik's select screens (Los geht's/Multiple
   Choice/Eintippen/Übung starten): much smaller than the driving-mode
   .btn-huge default (which they'd otherwise inherit) so they all fit on one
   iPhone screen, with no scrolling needed — and, just as importantly, so
   they're the same size across all three, instead of Auto's being huge
   while Quiz/Grammatik's are compact (see .center-text's comment on tab
   switching). */
.mode-choice-btn {
  min-height: auto;
  padding: 14px 18px;
  font-size: 1.15rem;
}

.mode-choice-btn .icon-inline-wrap.icon-lg {
  width: 24px;
  height: 24px;
  vertical-align: -7px;
}

.mode-choice-btn .hint {
  font-size: 0.78rem;
  margin-top: 3px;
}

.btn-icon {
  background: none;
  border: none;
  box-shadow: none;
  font-size: 1.2rem;
  padding: 4px 10px;
}

.btn-primary .hint,
.btn-success .hint,
.btn-danger .hint {
  color: inherit;
  opacity: 0.75;
}

.btn-huge .hint {
  display: block;
  margin-top: 6px;
  font-size: 0.85rem;
}

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}

/* Applied to the word/card content itself (not the whole screen incl. nav
   and buttons) so it doesn't flicker on every re-render — matters in Auto
   mode, where cards can change automatically every few seconds. */
.card-display,
.quiz-word,
.typing-answer {
  animation: fadeIn 0.2s ease;
}

/* --- Shared progress bar --- */

.progress-wrap {
  height: 6px;
  background: var(--bg-elevated-2);
  border-radius: 999px;
  overflow: hidden;
  border: 1px solid var(--border);
}

.progress-bar {
  height: 100%;
  background: var(--accent-gradient);
  border-radius: 999px;
  transition: width 0.35s ease;
}

.progress-text {
  text-align: center;
  color: var(--text-muted);
  font-size: 0.8rem;
  margin-top: 4px;
}

.quiz-mode .hint {
  font-size: 0.85rem;
}

/* The correct-translation feedback in Quiz/Eintippen ("Richtig!" /
   "Richtig wäre: ...") — bumped up from the muted, small .hint default so
   it's easy to read at a glance instead of blending into the background. */
.typing-result {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--text);
}

/* Quiz's "Zuhören" translation display — same reveal-pending
   pattern as Auto mode's .card-secondary, sized to match Quiz's more
   compact typography instead of Auto's driving-sized text. */
.quiz-secondary {
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--text);
  text-align: center;
}

.quiz-secondary.reveal-pending {
  opacity: 0.6;
  font-style: italic;
  font-weight: 400;
  color: var(--text-muted);
}

/* --- Direction / mode toggles (shared) --- */

.direction-toggle {
  display: flex;
  width: 100%;
  gap: 8px;
  margin-bottom: 8px;
}

.toggle-btn {
  flex: 1;
  padding: 12px 8px;
  font-size: 0.9rem;
}

.toggle-btn.active {
  background: var(--accent-gradient);
  border-color: transparent;
  color: var(--accent-text);
  font-weight: 700;
}

.flag-icon {
  width: 20px;
  height: 12px;
  vertical-align: middle;
  border-radius: 2px;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
}

.icon-inline-wrap {
  display: inline-flex;
  width: 20px;
  height: 20px;
  vertical-align: -5px;
  flex-shrink: 0;
}

.icon-inline-wrap svg {
  width: 100%;
  height: 100%;
}

.icon-inline-wrap.icon-lg {
  width: 30px;
  height: 30px;
  vertical-align: -9px;
}

/* Buttons that pair an icon with text (huge or otherwise) center them via flex
   rather than relying on vertical-align, so alignment stays correct
   regardless of icon/font size. */
.btn-with-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

.btn-with-icon .icon-inline-wrap {
  vertical-align: 0;
}

/* --- Audio mode (car use): oversized, high-contrast, minimal reading --- */

.audio-mode {
  display: flex;
  flex-direction: column;
  /* min-height (not height): matches .quiz-mode — see its comment for why a
     fixed height risks capping this box below its actual content. */
  min-height: 100%;
  /* Padding/gap match .quiz-mode's so Auto/Quiz/Grammatik share the same
     visual rhythm when switching between their nav tabs. */
  padding: 12px;
  gap: 10px;
}

.card-display {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 36px 16px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: 26px;
  box-shadow: var(--shadow);
  position: relative;
  overflow: hidden;
}

.card-display::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 5px;
  background: var(--accent-gradient);
}

@keyframes pulseCorrect {
  0% { box-shadow: var(--shadow), 0 0 0 0 rgba(52, 211, 153, 0.5); }
  70% { box-shadow: var(--shadow), 0 0 0 18px rgba(52, 211, 153, 0); }
  100% { box-shadow: var(--shadow), 0 0 0 0 rgba(52, 211, 153, 0); }
}

.card-display.pulse-correct {
  animation: pulseCorrect 0.7s ease;
}

@keyframes shakeIncorrect {
  10%, 90% { transform: translateX(-2px); }
  20%, 80% { transform: translateX(4px); }
  30%, 50%, 70% { transform: translateX(-7px); }
  40%, 60% { transform: translateX(7px); }
}

.card-display.shake-incorrect {
  animation: shakeIncorrect 0.5s ease;
}

.card-primary {
  font-size: 2.4rem;
  font-weight: 800;
  text-align: center;
}

.card-secondary {
  font-size: 1.6rem;
  color: var(--text-muted);
  text-align: center;
  animation: fadeIn 0.3s ease;
}

.card-secondary.reveal-pending {
  opacity: 0.6;
  font-style: italic;
}

.rate-buttons {
  display: flex;
  gap: 12px;
  flex: 1;
}

.rate-buttons .btn-huge {
  flex: 1;
}

/* Quiz's "Zuhören" reuses .rate-buttons, but Quiz's screens
   aren't stretched edge-to-edge the way Audio mode's are — flex:1 there
   just grows the row to fill whatever empty space is left below it,
   ballooning the buttons' height. Keep the row (and its buttons) their
   natural compact size instead. */
.quiz-mode .rate-buttons {
  flex: none;
}

.quiz-mode .rate-buttons .btn-huge {
  flex: 1;
}

.mic-status {
  text-align: center;
  font-size: 1.2rem;
  padding: 12px;
}

/* --- Quiz mode --- */

.quiz-mode {
  /* min-height (not height): a fixed height would cap this box at exactly the
     screen's visible height, so content taller than that (e.g. typing mode
     once the iOS keyboard eats vertical space) would only overflow it
     visually without growing its own box — and since .quiz-word's sticky
     positioning is computed relative to THIS box, a capped box scrolls away
     as a whole and drags the "stuck" word off-screen with it. min-height
     lets the box grow to fit all its content when needed, matching #view's
     actual scrollable area, while still filling the screen (via the 100%
     floor) in the normal case where content already fits. */
  min-height: 100%;
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* Wraps the word/options/feedback in active-question states so the action
   button below it (Weiter/Prüfen) is a fixed-size flex item that always
   stays within the visible screen — content that doesn't fit scrolls inside
   this wrapper instead of pushing the button off-screen. Real mobile Safari
   also shrinks the visible viewport further with its address/tab bars than
   a plain 100vh assumes, which plain content-flow sizing doesn't account for. */
.quiz-content {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.quiz-word {
  font-size: 1.5rem;
  font-weight: 800;
  text-align: center;
  padding: 14px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: 18px;
  box-shadow: var(--shadow-sm);
  /* Pinned to the top of the scrolling area so the word being tested can
     never scroll out of view — including when the iOS keyboard opens and
     Safari scrolls the focused input into view on its own, separately from
     (and not fully preventable via) the input's own focus() call. */
  position: sticky;
  top: 0;
  z-index: 3;
}

/* Grammar's prompt is a full sentence (with a blank), not a single word —
   left-aligned and a bit smaller so longer sentences wrap comfortably
   instead of looking like shouted single words. */
.grammar-sentence {
  text-align: left;
  font-size: 1.2rem;
  line-height: 1.4;
}

.grammar-explanation {
  font-size: 0.9rem;
  line-height: 1.4;
  color: var(--text-muted);
}

.quiz-options {
  display: grid;
  gap: 8px;
}

.btn-option {
  padding: 12px 14px;
  font-size: 1rem;
  text-align: left;
}

.btn-option.correct {
  background: var(--success-gradient);
  border-color: transparent;
  color: var(--success-text);
  box-shadow: 0 10px 24px rgba(52, 211, 153, 0.3);
}

.btn-option.incorrect {
  background: var(--danger-gradient);
  border-color: transparent;
  color: var(--danger-text);
  box-shadow: 0 10px 24px rgba(251, 113, 133, 0.3);
}

.btn-option.disabled {
  opacity: 0.92;
}

.typing-form {
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex-shrink: 0;
}

.typing-form input {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 14px;
  padding: 12px 16px;
  font-size: 1.15rem;
  text-align: center;
  width: 100%;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.typing-form input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(167, 139, 250, 0.25);
}

.typing-answer {
  text-align: center;
  font-size: 1.15rem;
  font-weight: 700;
  padding: 10px;
  border-radius: 16px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  animation: fadeIn 0.25s ease;
}

.typing-answer.correct {
  background: var(--success-gradient);
  border-color: transparent;
  color: var(--success-text);
}

.typing-answer.incorrect {
  background: var(--danger-gradient);
  border-color: transparent;
  color: var(--danger-text);
}

/* --- Manage mode --- */

.manage-mode section {
  margin-bottom: 20px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: 22px;
  padding: 18px;
  box-shadow: var(--shadow-sm);
}

.manage-mode h3 {
  margin: 0 0 10px;
  font-size: 1rem;
  letter-spacing: 0.01em;
  color: var(--accent-text);
}

/* Same specificity as ".manage-mode section" (class + type) so this actually
   overrides the flat background instead of losing to source order. */
section.account-box,
section.progress-box {
  background: linear-gradient(160deg, #f3effc 0%, var(--bg-elevated) 100%);
  margin-bottom: 20px;
}

.app-version {
  margin-top: -4px;
  font-size: 0.8rem;
  opacity: 0.6;
}

.progress-box h3 {
  display: flex;
  align-items: center;
  gap: 6px;
}

.stats-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
}

.stat-tile {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 14px;
  text-align: center;
}

.stat-value {
  font-size: 1.6rem;
  font-weight: 800;
  color: var(--accent-text);
}

.stat-with-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
}

.stat-label {
  font-size: 0.8rem;
  color: var(--text-muted);
  margin-top: 2px;
}

.account-box .btn {
  margin-right: 8px;
  margin-top: 8px;
}

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

.voice-row-label {
  font-size: 0.9rem;
  color: var(--text-muted);
  flex-shrink: 0;
  width: 64px;
}

.voice-select,
.field-select {
  min-width: 0;
  background: var(--bg-elevated-2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 12px;
  padding: 10px 12px;
  /* Exactly 16px (not the usual rem scale, which lands under 16px here) —
     iOS Safari auto-zooms the whole page in on any form control whose font
     size is below 16px when it gets focused/opened. */
  font-size: 16px;
}

.voice-select:focus,
.field-select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(167, 139, 250, 0.25);
}

/* .voice-select sits inside a horizontal .voice-row, where flex:1 correctly
   shares the row with its label/test button. .field-select instead stands
   alone inside a vertical, centered column (Grammatik's topic picker) —
   flex:1 there means flex-GROW along that column's main axis, which
   stretched the dropdown to fill the entire available height. */
.voice-select {
  flex: 1;
}

.field-select {
  flex: none;
  width: 100%;
}

.voice-row .btn-icon {
  flex-shrink: 0;
  border: 1px solid var(--border);
  border-radius: 12px;
}

.add-form {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.add-form input,
textarea {
  background: var(--bg-elevated-2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 12px;
  padding: 10px 12px;
  font-size: 1rem;
  width: 100%;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.add-form input:focus,
textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(167, 139, 250, 0.25);
}

#csv-file {
  margin-bottom: 8px;
  color: var(--text-muted);
}

.search-wrap {
  position: relative;
  margin-bottom: 10px;
}

.search-wrap .search-icon {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-muted);
  pointer-events: none;
}

.search-input {
  background: var(--bg-elevated-2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 12px;
  padding: 10px 12px 10px 40px;
  font-size: 1rem;
  width: 100%;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.search-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(167, 139, 250, 0.25);
}

.vocab-list {
  max-height: 50vh;
  overflow-y: auto;
}

.vocab-category h4 {
  color: var(--text-muted);
  margin: 16px 0 6px;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.vocab-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 9px 8px;
  border-radius: 12px;
  border-bottom: 1px solid var(--border);
  transition: background 0.15s ease;
}

.vocab-row:hover {
  background: var(--bg-elevated-2);
}

.row-actions {
  display: flex;
  gap: 2px;
  flex-shrink: 0;
}

.word-type-badge {
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--accent-text);
  background: var(--bg-elevated-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 1px 8px;
  vertical-align: middle;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.vocab-row-editing {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 8px;
  border-radius: 12px;
  background: var(--bg-elevated-2);
  border: 1px solid var(--accent);
}

.vocab-row-editing input {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 10px;
  padding: 8px 10px;
  font-size: 0.95rem;
  width: 100%;
}

.vocab-row-editing input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(167, 139, 250, 0.25);
}

.edit-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}

.edit-actions .btn-icon.btn-primary {
  background: var(--accent-gradient);
  color: var(--accent-text);
}
