:root {
  --bg: #fef9f0;
  --card-bg: #ffffff;
  --primary: #4a7bf7;
  --primary-dark: #3560d6;
  --addition: #ff9f43;
  --subtraction: #26c6a3;
  --multiplication: #a06bf7;
  --tables: #ec5990;
  --early-learning: #ffca28;
  --numbers: #00acc1;
  --text: #2b2b3a;
  --muted: #7a7a8c;
  --correct: #2ecc71;
  --incorrect: #ff5b5b;
  --border-radius: 18px;
  font-size: 18px;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: 'Comic Sans MS', 'Segoe UI', Verdana, sans-serif;
  min-height: 100vh;
}

#app {
  max-width: 960px;
  margin: 0 auto;
  padding: 24px 16px 60px;
}

.loading-screen {
  text-align: center;
  padding-top: 120px;
  color: var(--muted);
}

.auth-screen {
  max-width: 380px;
  margin: 60px auto 0;
  background: var(--card-bg);
  border-radius: var(--border-radius);
  padding: 28px 24px;
  box-shadow: 0 3px 12px rgba(0, 0, 0, 0.08);
  text-align: center;
}

.auth-subtitle {
  color: var(--muted);
  margin: 0 0 20px;
}

.auth-field {
  display: block;
  text-align: left;
  margin-bottom: 8px;
}

.auth-field span {
  display: block;
  font-size: 0.85rem;
  color: var(--muted);
  margin-bottom: 6px;
}

.auth-field input {
  width: 100%;
  font-family: inherit;
  font-size: 1.1rem;
  padding: 12px 14px;
  border: 2px solid var(--primary);
  border-radius: 10px;
  color: var(--text);
}

.auth-hint {
  font-size: 0.8rem;
  color: var(--muted);
  margin: 0 0 20px;
  text-align: left;
}

.auth-error {
  color: var(--incorrect);
  font-size: 0.9rem;
  margin-bottom: 16px;
}

.auth-stay-signed-in {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.9rem;
  color: var(--muted);
  margin: 4px 0 20px;
  cursor: pointer;
}

.auth-stay-signed-in input {
  cursor: pointer;
}

.auth-screen > .btn-primary {
  width: 100%;
  margin-bottom: 10px;
}

.member-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 20px;
}

.member-select-btn {
  width: 100%;
}

/* The "brand new parent, zero members yet" bootstrap form on the
   switch-member screen (see selectMemberScreenHtml, app.js) — just a name
   input + Add button today. display: flex + gap guarantees a fixed, even
   space between them regardless of the input's own rendered width, rather
   than relying on inline-element text-wrapping (which depends on the
   browser's default input size AND font metrics, and can visually crowd
   the button against the input on some devices). */
.add-member-row {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 16px;
}

.add-member-row > input {
  width: 100%;
  font-family: inherit;
  font-size: 1rem;
  padding: 10px 12px;
  border: 2px solid var(--primary);
  border-radius: 10px;
  color: var(--text);
}

/* Reuses .member-edit-row/.member-edit-field for its two fields (see below)
   so they're guaranteed identical in size to the already-added-member rows
   by construction, not by separately tuned copies that can drift apart. The
   "+" button rides along in the same row now that the DOB field is a fixed
   width (.member-edit-field-fixed) rather than a growable one — it no
   longer steals space from the fields the way it did when both were
   flex-growable. */
/* The fields sit inside a <label> with a trailing 10px margin-bottom
   (.member-edit-field label), so flex-end alignment puts the button 10px
   below the inputs' actual borders — matching that margin here pulls it
   back up to line up with the input boxes themselves. */
button.add-member-submit {
  flex-shrink: 0;
  width: 47px;
  height: 47px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 10px;
  /* Owning its own glyph size (rather than relying on whichever other class
     happens to be combined with it, e.g. .btn-home-icon) keeps every +/-
     button this class is used on — Member details, Login emails, Mobile
     numbers — visually consistent by construction, not by remembering to
     also tack on a sizing class every time it's reused somewhere new. */
  font-size: 1.4rem;
}

.home-greeting {
  font-family: 'Brush Script MT', 'Lucida Handwriting', cursive;
  font-size: 1.8rem;
  text-align: center;
  color: var(--primary);
  margin: -8px 0 20px;
}

.sync-status {
  position: fixed;
  top: 10px;
  right: 14px;
  font-size: 0.8rem;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--card-bg);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
  color: var(--muted);
  z-index: 10;
}

.sync-status:empty {
  display: none;
}

.sync-status-error {
  color: var(--incorrect);
  font-weight: 700;
}

.btn {
  font-family: inherit;
  font-size: 1.15rem;
  font-weight: 700;
  border: none;
  border-radius: 999px;
  padding: 16px 28px;
  cursor: pointer;
  transition: transform 0.1s ease, box-shadow 0.1s ease;
}

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

.btn-primary {
  background: var(--primary);
  color: white;
}

/* Same filled-button treatment as .btn-primary (background/text/shadow),
   just dark pink instead of blue — used for the delete-member "−" button. */
.btn-danger-filled {
  background: #c2185b;
  color: white;
}

.btn-secondary {
  background: white;
  color: var(--primary);
  border: 2px solid var(--primary);
  width: 100%;
}

.btn-secondary:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Just "Practice" now (no more "Practice 10 min"), so it no longer needs
   .btn-secondary's full card width — sized to its short label and centered
   instead, with a fill-in-on-hover effect like the app's other outline
   buttons (.btn-outline-primary etc.) already have. */
.btn-practice {
  display: block;
  width: auto;
  margin: 0 auto;
  padding: 10px 22px;
  font-size: 1rem;
}

.btn-practice:hover:not(:disabled) {
  background: var(--primary);
  color: white;
}

.btn-link {
  background: none;
  color: var(--muted);
  text-decoration: underline;
  font-size: 1rem;
  padding: 8px;
  box-shadow: none;
}

.btn-outline-primary {
  background: white;
  color: var(--primary);
  border: none;
  box-shadow: none;
  text-decoration: none;
}

.btn-outline-primary:hover {
  background: var(--bg);
}

.btn-outline-danger {
  background: white;
  color: var(--incorrect);
  border: none;
  box-shadow: none;
  text-decoration: none;
}

.btn-outline-danger:hover {
  background: var(--bg);
}

.btn-icon-only {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.85rem;
  line-height: 1;
}

/* Fixed at 2 icons' width (28px each — .btn-icon-only) — 👁️ and 🔄 both
   always show, complete or not (🔄 redoes an already-mastered level too) —
   .progress-bar-col fills whatever's left over in the row, so a variable
   icon count here would make the progress bar a different width card to
   card depending on completion state. */
.op-icon-actions {
  display: flex;
  justify-content: center;
  gap: 0;
  width: 56px;
  flex-shrink: 0;
}

.progress-row {
  display: flex;
  align-items: center;
  gap: 0;
  margin: 24px 0 6px;
}

.progress-bar-col {
  flex: 1;
  min-width: 0;
}

.home-icon-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 16px;
  margin-bottom: 20px;
}

/* Home screen */
.app-title {
  text-align: center;
  font-size: 2.4rem;
  margin-bottom: 20px;
}

/* The auth screens (login/otp/switch-member) are a fixed narrow 380px card —
   the home screen's larger title size wraps awkwardly there, so it needs
   its own smaller, non-wrapping size in this context. */
.auth-screen .app-title {
  font-size: 1.7rem;
  white-space: nowrap;
}

.btn-home-icon {
  width: 40px;
  height: 40px;
  font-size: 1.4rem;
}

.op-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: 20px;
}

.op-card {
  background: var(--card-bg);
  border-radius: var(--border-radius);
  padding: 20px;
  box-shadow: 0 3px 12px rgba(0,0,0,0.08);
  border-top: 6px solid var(--primary);
}

.op-addition { border-top-color: var(--addition); }
.op-subtraction { border-top-color: var(--subtraction); }
.op-multiplication { border-top-color: var(--multiplication); }
.op-tables { border-top-color: var(--tables); }
.op-addition2 { border-top-color: var(--addition); }
.op-subtraction2 { border-top-color: var(--subtraction); }
.op-multiplication2 { border-top-color: var(--multiplication); }
.op-earlyLearning { border-top-color: var(--early-learning); }
.op-numbers { border-top-color: var(--numbers); }

/* The home screen's 3 topic cards — the whole card is the click target
   (no separate button), so it needs its own hover/active affordance.
   Their header has nothing below it (no level/progress row, unlike a
   subdivision card), so the 2-line title reservation and gap that exist
   for those don't apply here. */
.topic-card {
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.topic-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 18px rgba(0,0,0,0.14);
}

.topic-card:active {
  transform: translateY(0);
  box-shadow: 0 3px 12px rgba(0,0,0,0.08);
}

.topic-card .op-card-header {
  min-height: 0;
  margin-bottom: 0;
}

/* Frozen to the bottom of the viewport, not the page — .home-screen below
   gets matching bottom padding so the last topic card never sits behind
   it. Sits under any open modal (modal-overlay's z-index is 100).
   Collapsed by default: only the "▲ Feedback" toggle bar shows; clicking
   it reveals the form as a panel that grows upward (the bar is anchored
   to bottom:0, so added content pushes its top edge up, not down off
   screen). */
.feedback-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 20;
  background: var(--card-bg);
  box-shadow: 0 -3px 12px rgba(0,0,0,0.1);
  display: flex;
  flex-direction: column;
}

.home-screen {
  padding-bottom: 44px;
}

.feedback-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  border: none;
  background: none;
  font-family: inherit;
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--primary);
  padding: 8px 16px;
  cursor: pointer;
}

.feedback-toggle:hover {
  background: rgba(0, 0, 0, 0.04);
}

/* Draws the eye while collapsed only — stops the moment the panel opens,
   since blinking behind an open form the user is actively filling in
   would just be annoying rather than attention-grabbing. */
.feedback-toggle.attention {
  animation: feedback-toggle-blink 1.8s ease-in-out infinite;
}

@keyframes feedback-toggle-blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.4; }
}

@media (prefers-reduced-motion: reduce) {
  .feedback-toggle.attention {
    animation: none;
  }
}

.feedback-toggle-arrow {
  display: inline-block;
}

.feedback-bar-body {
  padding: 10px 16px 4px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.feedback-bar-extra {
  display: flex;
  align-items: center;
  gap: 10px;
}

.feedback-bar-row {
  display: flex;
  align-items: center;
  gap: 8px;
  max-width: 960px;
  width: 100%;
  margin: 0 auto;
}

.feedback-contact-input,
.feedback-text-input {
  box-sizing: border-box;
  font-family: inherit;
  font-size: 0.95rem;
  padding: 9px 12px;
  border: 2px solid var(--primary);
  border-radius: 10px;
  color: var(--text);
  background: var(--bg);
  min-width: 0;
}

.feedback-contact-input {
  flex: 0 1 190px;
  min-width: 165px;
}

.feedback-text-input {
  flex: 1 1 auto;
}

.feedback-attachment-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  width: fit-content;
  max-width: 100%;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--bg);
  font-size: 0.8rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.feedback-attachment-remove {
  flex-shrink: 0;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font-size: 0.8rem;
  color: var(--incorrect);
}

.feedback-submit-btn {
  width: 42px;
  height: 42px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 2px solid var(--primary);
  background: var(--card-bg);
  color: var(--primary);
  font-size: 1.1rem;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.feedback-submit-btn:hover {
  background: var(--primary);
  color: white;
}

.feedback-submit-btn.submitting {
  opacity: 0.6;
  cursor: default;
}

.feedback-submit-btn.success {
  border-color: var(--correct);
  background: var(--correct);
  color: white;
}

.op-card-header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
  /* Reserves 2 lines of title height always, not just when a title actually
     wraps — "Multiplication Tables" wraps to 2 lines at some grid widths
     while the other three stay on 1, which (via CSS Grid's default row
     stretch) made every card sharing that row taller than a card with no
     row-mate to stretch against, a real reported inconsistency. */
  min-height: 3.36rem;
}

.op-card-header h2 {
  margin: 0;
  font-size: 1.4rem;
  line-height: 1.2;
}

/* Words to Numbers / Number to Words sit side by side on the Numbers
   topic screen, and at the default heading size "Words to Numbers" alone
   was just barely too wide for the card and wrapped to 2 lines while its
   shorter neighbor stayed on 1 — an inconsistency between two cards a
   parent looks at side by side, not just a height mismatch (min-height
   above already handles keeping the CARDS the same height regardless).
   A slightly smaller size for these two specifically is enough for both
   to fit on one line, so neither wraps. */
.op-wordsToNumbers .op-card-header h2,
.op-numbersInWords .op-card-header h2 {
  font-size: 1.2rem;
}

.op-symbol-badge {
  font-size: 1.6rem;
  font-weight: 900;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
}

.op-level {
  color: var(--muted);
  font-size: 0.95rem;
  margin-bottom: 12px;
  text-align: center;
  line-height: 1.5;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.progress-bar {
  position: relative;
  height: 18px;
  background: #eee;
  border-radius: 999px;
  overflow: visible;
}

.progress-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--primary), var(--primary-dark));
  border-radius: 999px;
  transition: width 0.3s ease;
}

.progress-pointer {
  position: absolute;
  top: -26px;
  transform: translateX(-50%);
  background: var(--text);
  color: white;
  font-size: 0.75rem;
  padding: 2px 6px;
  border-radius: 6px;
  white-space: nowrap;
}

.progress-pointer::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -4px;
  transform: translateX(-50%);
  border: 4px solid transparent;
  border-top-color: var(--text);
}

.progress-label {
  font-size: 0.85rem;
  color: var(--muted);
  margin-bottom: 14px;
  text-align: center;
}

.progress-complete {
  font-weight: 700;
  color: var(--correct);
  margin: 20px 0;
}

/* Leaderboard */
.leaderboard-screen {
  max-width: 700px;
  margin: 0 auto;
}

.leaderboard-panel {
  background: var(--card-bg);
  border-radius: var(--border-radius);
  padding: 16px;
  box-shadow: 0 3px 12px rgba(0,0,0,0.08);
}

.leaderboard-controls {
  display: flex;
  gap: 8px;
  margin-bottom: 10px;
}

.leaderboard-controls select {
  flex: 1;
  min-width: 0;
  font-family: inherit;
  font-size: 0.85rem;
  padding: 6px 4px;
  border: 2px solid var(--primary);
  border-radius: 8px;
  color: var(--text);
  background: white;
}

.leaderboard-scope-toggle {
  display: flex;
  justify-content: center;
  gap: 14px;
  margin-bottom: 10px;
}

.leaderboard-facets {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
}

.leaderboard-facets select {
  flex: 1;
  min-width: 100px;
  font-family: inherit;
  font-size: 0.8rem;
  padding: 6px 4px;
  border: 2px solid var(--muted);
  border-radius: 8px;
  color: var(--text);
  background: white;
}

.leaderboard-scope-toggle .btn-link {
  text-decoration: none;
  font-size: 0.85rem;
  padding: 2px 6px;
}

.leaderboard-scope-active {
  color: var(--primary) !important;
  font-weight: 700;
  text-decoration: underline !important;
}

.leaderboard-status {
  color: var(--muted);
  font-size: 0.9rem;
  text-align: center;
  padding: 16px 4px;
}

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

.leaderboard-list li {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 4px;
  border-bottom: 1px solid var(--bg);
  font-size: 0.9rem;
}

.leaderboard-list li:last-child {
  border-bottom: none;
}

.leaderboard-you {
  background: var(--bg);
  border-radius: 8px;
  font-weight: 700;
}

.leaderboard-rank {
  width: 30px;
  flex-shrink: 0;
  color: var(--muted);
}

.leaderboard-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.leaderboard-location {
  display: block;
  font-size: 0.75rem;
  font-weight: 400;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.leaderboard-time {
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
  color: var(--primary);
}

/* Practice Time (⏱️) */
.practice-time-screen {
  max-width: 700px;
  margin: 0 auto;
}

.practice-time-panel {
  background: var(--card-bg);
  border-radius: var(--border-radius);
  padding: 16px;
  box-shadow: 0 3px 12px rgba(0,0,0,0.08);
}

.practice-time-status {
  color: var(--muted);
  font-size: 0.9rem;
  text-align: center;
  padding: 16px 4px;
}

.practice-time-day {
  padding: 8px 0;
  border-bottom: 1px solid var(--bg);
}

.practice-time-day:last-child {
  border-bottom: none;
}

.practice-time-day-header {
  display: flex;
  justify-content: space-between;
  font-weight: 700;
  padding: 4px;
}

.practice-time-day-total {
  font-variant-numeric: tabular-nums;
  color: var(--primary);
}

.practice-time-op-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.practice-time-op-list li {
  display: flex;
  justify-content: space-between;
  padding: 4px 4px 4px 16px;
  font-size: 0.9rem;
  color: var(--text);
}

.practice-time-op-seconds {
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}

.fact-history-modal-content {
  max-width: 480px;
}

.fact-history-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.fact-history-empty {
  color: var(--muted);
  font-size: 0.9rem;
  text-align: center;
  padding: 16px 4px;
}

.fact-history-event {
  display: flex;
  gap: 10px;
  padding: 10px 12px;
  border-radius: var(--border-radius);
  background: var(--card-bg);
  border-left: 4px solid var(--muted);
}

.fact-history-event-correct {
  border-left-color: var(--correct);
}

.fact-history-event-wrong {
  border-left-color: var(--incorrect);
}

.fact-history-icon {
  flex-shrink: 0;
  font-size: 1.1rem;
  line-height: 1.4;
}

.fact-history-event-body {
  flex: 1;
  min-width: 0;
}

.fact-history-event-top {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  font-size: 0.85rem;
}

.fact-history-time {
  color: var(--text);
}

.fact-history-duration {
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}

.fact-history-phrasing {
  margin-top: 2px;
  font-size: 0.8rem;
  color: var(--muted);
}

.fact-history-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 6px;
}

.fact-history-tag {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  padding: 2px 6px;
  border-radius: 999px;
  background: var(--bg);
  color: var(--muted);
}

.fact-history-tag-mastered {
  background: var(--primary);
  color: white;
}

.fact-history-tag-slow {
  color: #b5651d;
}

.fact-history-tag-redo {
  color: var(--primary);
}

.details-history-btn {
  display: block;
  width: 100%;
  text-align: left;
  white-space: normal;
  padding: 0;
  font-size: inherit;
  line-height: inherit;
  color: inherit;
}

.family-settings {
  background: var(--card-bg);
  border-radius: var(--border-radius);
  padding: 20px;
  box-shadow: 0 3px 12px rgba(0,0,0,0.08);
  margin-top: 20px;
}

.family-settings-heading {
  margin: 0 0 14px;
  font-size: 1.05rem;
  text-align: center;
}

.family-settings-hint {
  font-size: 0.8rem;
  color: var(--muted);
  text-align: center;
  margin: -6px 0 14px;
}

.family-settings-field {
  display: block;
  margin-bottom: 12px;
}

/* The "add another login email / mobile number" row — an input plus a
   round "+" button (.add-member-submit, reused as-is for identical sizing).
   Without align-items:center, the row's default flex stretch — combined
   with .add-member-submit's own margin-bottom (needed elsewhere, to line it
   up against a <label>'s trailing margin, which doesn't exist in this
   label-less row) — stretched this plain input a few pixels taller than
   every other textbox on the page. */
.list-add-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}

.list-add-row .add-member-submit {
  margin-bottom: 0;
}

.list-add-row input {
  flex: 1;
  min-width: 0;
  font-family: inherit;
  font-size: 1rem;
  padding: 10px 12px;
  border: 2px solid var(--primary);
  border-radius: 10px;
  color: var(--text);
}

/* Fixed width, just enough for a "+" plus 3-4 digits (+91, +974, …) —
   never grows or shrinks, so the actual number field (its .list-add-row
   sibling, still flex:1) always gets the rest of the row's width.
   Selector needs ".list-add-row" in front to out-specificity
   ".list-add-row input" above (a bare ".mobile-country-code-input" loses
   to that class+element selector regardless of source order — it was
   silently being overridden down to flex:1 before this). */
.list-add-row .mobile-country-code-input {
  flex: 0 0 60px;
  min-width: 0;
  text-align: center;
  padding-left: 4px;
  padding-right: 4px;
}

.list-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  /* No horizontal padding, to match .list-add-row (which has none) --
     otherwise its "-" button sits a few pixels left of the "+" button
     directly above it instead of lining up flush with the same edge. */
  padding: 8px 0;
  border-bottom: 1px solid #eee;
}

/* Flex items default to min-width:auto, which lets a long, space-less
   string (an email has nowhere to naturally break) overflow the row
   instead of wrapping — that's what was dragging the +/- button out of
   line between rows of different lengths. min-width:0 lets this shrink to
   fit the row; overflow-wrap:anywhere then allows breaking the text itself
   (mid-word, since there's no space to break at) once it's out of room, so
   the button stays pinned at the same spot on every row regardless of how
   long the email/number is. */
.list-item > span {
  min-width: 0;
  overflow-wrap: anywhere;
}

.list-item:last-of-type {
  border-bottom: none;
}

.list-item-tag {
  font-size: 0.7rem;
  color: var(--muted);
  background: var(--bg);
  padding: 2px 8px;
  border-radius: 999px;
  margin-left: 6px;
}

.family-settings-row {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}

.family-settings-col {
  flex: 1 1 220px;
  min-width: 0;
}

/* Login emails and Mobile numbers are each a full standalone .family-settings
   card (not just a couple of input fields like the Country/City row), so
   this row needs its own top margin and gap rather than inheriting each
   card's usual margin-top — otherwise the top margin doubles up with the
   row's own gap once the cards wrap to stacked on a narrow screen. */
.family-settings-row-cards {
  margin-top: 20px;
  row-gap: 20px;
  column-gap: 16px;
}

.family-settings-row-cards .family-settings {
  margin-top: 0;
}

.family-settings-field span {
  display: block;
  font-size: 0.8rem;
  color: var(--muted);
  margin-bottom: 6px;
}

.family-settings-field input,
.family-settings-field select {
  width: 100%;
  font-family: inherit;
  font-size: 1rem;
  padding: 10px 12px;
  border: 2px solid var(--primary);
  border-radius: 10px;
  color: var(--text);
  background: white;
}

.family-settings-field input:disabled,
.family-settings-field select:disabled {
  border-color: #ccc;
  color: var(--muted);
  background: #f3f3f3;
  cursor: not-allowed;
}

.settings-screen {
  max-width: 700px;
  margin: 0 auto;
}

/* Popup version of the Family screen, opened from the home screen's family
   icon (see settingsModalHtml) — dims and blocks the home screen behind it
   rather than navigating away from it. */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(43, 43, 58, 0.6);
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding: 40px 16px;
  /* No outer scroll — a popup taller than the screen scrolls internally
     (see .modal-content's own overflow-y below), never the dimmed backdrop
     behind it. */
  overflow: hidden;
  z-index: 100;
}

.modal-content {
  background: var(--bg);
  border-radius: var(--border-radius);
  width: 100%;
  max-width: 700px;
  /* Caps at whatever room .modal-overlay's own padding leaves in the
     viewport, so a popup that would otherwise be taller than the screen
     scrolls inside itself instead of pushing the backdrop into a page
     scroll. */
  max-height: 100%;
  overflow-y: auto;
  padding: 24px 16px 32px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.35);
}

/* .auth-screen is normally its own standalone card (the full-page login
   flow) — inside the switch-member popup, .modal-content already provides
   that card, so strip auth-screen's own margin/background/shadow to avoid
   a card nested inside a card. */
.modal-content .auth-screen {
  max-width: 380px;
  margin: 0 auto;
  background: none;
  box-shadow: none;
  padding: 0;
}

.settings-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}

.settings-header .app-title {
  margin: 0;
  font-size: 1.6rem;
}

.install-steps {
  margin: 16px 0 4px;
  padding-left: 24px;
  line-height: 1.8;
  font-size: 1rem;
}

.install-steps li {
  margin-bottom: 8px;
}

.settings-header .btn-link {
  text-decoration: none;
  font-size: 0.9rem;
  white-space: nowrap;
}

.settings-hint {
  font-size: 0.85rem;
  color: var(--muted);
  margin: 0 0 14px;
}

.family-settings-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.9rem;
  color: var(--muted);
  margin-bottom: 14px;
  cursor: pointer;
}

.reset-warning {
  color: var(--muted);
  font-size: 0.9rem;
  margin: 0 0 12px;
}

.reset-everything-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  width: 100%;
  box-sizing: border-box;
  padding: 10px 14px;
  border: 2px solid var(--incorrect);
  border-radius: 12px;
  margin-bottom: 18px;
  cursor: pointer;
}

.reset-everything-row input[type='checkbox'] {
  margin-top: 4px;
  flex-shrink: 0;
}

.reset-everything-text {
  color: var(--incorrect);
  line-height: 1.4;
}

.reset-op-section {
  margin-bottom: 16px;
}

.reset-op-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 4px;
}

.reset-op-header h3 {
  margin: 0;
}

.reset-op-header .btn-link {
  padding: 4px 6px;
  font-size: 0.85rem;
}

.reset-level-list {
  max-height: 180px;
  overflow-y: auto;
  border: 2px solid #eee;
  border-radius: 8px;
  padding: 6px 10px;
}

.reset-level-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 0;
  font-size: 0.9rem;
  cursor: pointer;
}

.reset-confirm-area {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 2px solid #eee;
}

/* Same idea as the Tables worksheet — header and the confirm-area footer
   stay fixed, only .reset-scroll-body (the warning text + checklists,
   which is what actually grows long) scrolls inside itself. */
.reset-modal-content {
  max-height: 100%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.reset-modal-content .settings-header,
.reset-modal-content .reset-confirm-area {
  flex-shrink: 0;
}

.reset-scroll-body {
  /* Matches .family-settings' own card look (background/padding/shadow) —
     this replaces that wrapper here so the scrollable region still reads
     as the same card, just now flex-sized instead of a static block. */
  background: var(--card-bg);
  border-radius: var(--border-radius);
  padding: 20px;
  box-shadow: 0 3px 12px rgba(0, 0, 0, 0.08);
  margin-top: 20px;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}

.reset-selection-summary {
  font-size: 0.9rem;
  color: var(--incorrect);
  font-weight: 600;
}

.reset-selection-summary.reset-selection-empty {
  color: var(--muted);
  font-weight: 400;
}

.reset-confirm-label {
  display: block;
  margin: 12px 0 6px;
  font-size: 0.9rem;
}

.reset-confirm-input {
  display: block;
  width: 100%;
  margin-top: 6px;
  padding: 8px 10px;
  border: 2px solid #ccc;
  border-radius: 8px;
  font-size: 1rem;
  box-sizing: border-box;
}

.reset-confirm-error {
  color: var(--incorrect);
  font-size: 0.85rem;
  margin: 4px 0 0;
}

.reset-apply-btn {
  width: 100%;
  margin-top: 12px;
}

.reset-apply-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.settings-save-status {
  font-size: 0.8rem;
  color: var(--muted);
}

.settings-save-status-ok {
  color: var(--correct);
  font-weight: 700;
}

.dob-prompt {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 2px dashed var(--bg);
}

.member-edit-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 16px;
}

/* Reused as-is by the "add a member" row (see .add-member-row above) so its
   fields are pixel-identical in width and height to these — one rule, not
   two copies that can drift apart. */
.member-edit-field {
  flex: 1 1 200px;
  min-width: 0;
  position: relative;
}

/* .member-edit-row bottom-aligns its columns (align-items: flex-end) so the
   delete button sits level with the input boxes rather than the labels —
   that only works if every column is the same height. An error or "Saved"
   status appearing under just one field's input would normally make that
   one column taller, which then drags every sibling column down with it
   (flex-end keeps their bottoms level with the now-taller one). Taking
   this out of the flow entirely, so it floats below without adding to the
   column's own height, keeps the whole row's alignment unaffected either
   way. */
.member-edit-field .auth-error,
.member-edit-field .settings-save-status {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  margin-top: 2px;
  white-space: nowrap;
}

/* The DOB field stays a fixed width — a date never needs more room than
   this, so any extra space in the row goes entirely to the name field
   instead of stretching the date box pointlessly wide. */
.member-edit-field-fixed {
  flex: 0 0 170px;
}

/* Age is computed, not editable, so it's a plain read-only-looking box
   rather than an <input> — sized just wide enough for a 1-2 digit number.
   margin-bottom matches the other fields' label trailing margin so this
   field's block height still lines up with its row siblings. */
.member-edit-field-age {
  flex: 0 0 47px;
  margin-bottom: 10px;
}

.age-display {
  width: 100%;
  height: 47px;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: inherit;
  font-size: 1rem;
  padding: 8px 10px;
  border: 2px solid var(--primary);
  border-radius: 10px;
  background: #f3f3f3;
  color: var(--muted);
}

.member-edit-field label {
  display: block;
  margin-bottom: 10px;
}

.member-edit-field span {
  display: block;
  font-size: 0.8rem;
  color: var(--muted);
  margin-bottom: 6px;
}

.member-edit-field input {
  width: 100%;
  height: 47px;
  font-family: inherit;
  font-size: 1rem;
  padding: 8px 10px;
  border: 2px solid var(--primary);
  border-radius: 10px;
  color: var(--text);
}

/* Replaces the browser's default focus ring (a black outline that clashes
   with the app's blue fields) with a darker border in each field's own
   color, keeping its existing 3D shadow as-is. */
.auth-field input:focus,
.add-member-row > input:focus,
.leaderboard-controls select:focus,
.family-settings-field input:focus,
.family-settings-field select:focus,
.member-edit-field input:focus {
  outline: none;
  border-color: var(--primary-dark);
}

.leaderboard-facets select:focus {
  outline: none;
  border-color: #5c5c6e;
}

/* Quiz screen */
/* Header/level/timing/progress bar, the problem itself, the keypad, and the
   pause/home footer all stay fixed — .quiz-pictures (the one part that can
   genuinely grow tall, e.g. a big multiplication picture) is the only
   scrollable exception. Mirrors the same pattern as the Tables worksheet,
   Reset Progress, and Details screen. */
.quiz-modal-content {
  max-height: 100%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.quiz-screen {
  background: var(--card-bg);
  border-radius: var(--border-radius);
  padding: 24px;
  box-shadow: 0 3px 12px rgba(0,0,0,0.08);
  text-align: center;
  transition: background 0.2s ease;
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}

.quiz-screen > *:not(.quiz-pictures) {
  flex-shrink: 0;
}

.quiz-screen.feedback-correct {
  background: #e8fbf1;
}

.quiz-screen.feedback-incorrect {
  background: #fdeaea;
}

.quiz-header {
  display: flex;
  justify-content: space-between;
  /* flex-start, not center — the timer block now carries 4 lines (timer,
     start time, level avg, this question), so centering against it would
     push "Addition" down away from the timer digits it should sit level
     with. */
  align-items: flex-start;
  font-size: 1.2rem;
  font-weight: 700;
}

.quiz-header-left {
  display: flex;
  flex-direction: column;
  gap: 3px;
  /* .quiz-screen sets text-align:center for the rest of the screen (the
     problem, keypad, etc.) — override it here so the title stays flush left
     above "Level 2" / "Adding 0" instead of centering within the stretched
     flex column. */
  text-align: left;
}

.quiz-timer-block {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 3px;
}

.quiz-timer {
  font-variant-numeric: tabular-nums;
  background: var(--bg);
  padding: 4px 14px;
  border-radius: 999px;
}

.quiz-start-time {
  font-size: 0.7rem;
  font-weight: 400;
  color: var(--muted);
}

/* Now sits in the header's left column, next to the operation title
   (mirrors .quiz-timing on the right) rather than its own centered row —
   left-aligned and sized down to match .quiz-start-time's subtlety so the
   title stays the visually dominant line. */
.quiz-level {
  color: var(--muted);
  text-align: left;
  font-size: 0.7rem;
  font-weight: 400;
  line-height: 1.4;
}

.quiz-trial-badge {
  display: inline-block;
  margin-top: 4px;
  padding: 2px 10px;
  /* A fixed radius, not 999px — now that this sits in the narrower header
     column it can wrap to 2 lines, and a pill-sized radius rounds so far
     into a short-but-wide box that the wrapped second line's text spills
     past the background near the corner. A modest radius reads fine as a
     badge whether it wraps or not. */
  border-radius: 8px;
  background: #fff3cd;
  color: #8a6500;
  font-size: 0.7rem;
  font-weight: 600;
}

/* Now nested inside .quiz-timer-block (top-right, alongside the session
   timer and start time) rather than its own centered row — stacks the same
   way .quiz-start-time does. */
.quiz-timing {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 1px;
  font-size: 0.7rem;
  font-weight: 400;
  color: var(--muted);
}

.quiz-elapsed-value {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
}

.quiz-elapsed-fast {
  color: var(--correct);
}

.quiz-elapsed-medium {
  color: #d99a1b;
}

.quiz-elapsed-slow {
  color: var(--incorrect);
}

.quiz-progress {
  margin: 24px 0 16px;
}

.quiz-pictures {
  margin-bottom: 20px;
  min-height: 0;
  overflow-y: auto;
}

.quiz-problem {
  font-size: 3rem;
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  margin-bottom: 8px;
  flex-wrap: wrap;
}

.op-symbol {
  color: var(--primary);
}

.answer-box {
  min-width: 110px;
  min-height: 70px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--bg);
  border: 3px solid var(--primary);
  border-radius: 12px;
  padding: 4px 12px;
}

.feedback-indicator {
  font-size: 2.5rem;
  height: 48px;
  margin-bottom: 10px;
}

.quiz-paused {
  padding: 40px 0;
  color: var(--muted);
  font-size: 1.3rem;
  font-weight: 700;
}

.quiz-paused-icon {
  font-size: 2.8rem;
  margin-bottom: 8px;
}

.quiz-footer-actions {
  display: flex;
  justify-content: center;
  gap: 20px;
  margin-top: 12px;
}

.btn-footer-icon {
  width: 44px;
  height: 44px;
  font-size: 1.3rem;
}

.keypad {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  /* width, not max-width: .quiz-screen is a flex column (needed to freeze
     the header/footer and let only .quiz-pictures scroll — see above), which
     makes this a flex item. A flex item's auto flex-basis for a 3-column fr
     grid resolves to a much smaller intrinsic size than 320px, shrinking
     every key — same fix as .tables-keypad below for the same reason. */
  width: 320px;
  max-width: 100%;
  flex-shrink: 0;
  margin: 0 auto 16px;
}

.key {
  font-size: 1.5rem;
  font-weight: 700;
  padding: 18px 0;
  border-radius: 14px;
  border: none;
  background: var(--bg);
  color: var(--text);
  cursor: pointer;
}

.key:active {
  transform: scale(0.94);
}

.key-submit {
  background: var(--correct);
  color: white;
}

.key-backspace {
  background: var(--incorrect);
  color: white;
}

/* --long-form-width (set inline per-problem, app.js) is the row's own cell
   count including the operator column — anywhere from 4 (the original 2D×1D,
   up to a 3-digit answer) to 8 (4D×3D, up to a 7-digit answer — see
   MULTIPLICATION_LONG_FORM_COMBOS, levels.js). --long-form-cell-w derives
   the actual cell size from it: 44px (.long-form-cell's original fixed
   size) whenever that comfortably fits every column across the viewport,
   shrinking below 44px only once it wouldn't — the same clipping bug an
   earlier fixed cell size caused on Table 20's 3-digit answers, but general
   over any column count instead of a one-off breakpoint fix. 90px
   approximates the modal/card padding outside .long-form-problem at the
   narrowest supported width (see the 480px media query below); every other
   size on this problem (row height, rule width, font sizes) derives from
   this one value so the whole grid scales together instead of cells
   shrinking to fit while their text overflows them. */
.long-form-problem {
  --long-form-cell-w: min(44px, calc((100vw - 90px) / var(--long-form-width, 4)));
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  margin-bottom: 12px;
}

.long-form-row {
  display: flex;
  justify-content: center;
  gap: 6px;
}

/* Also the base size for .long-form-answer-cell below (applied together on
   the same element) — a blank a/b-row cell (left-padding for a shorter
   operand) and an untyped answer cell should occupy identically-sized
   space, so the three rows always line up column for column. Height and
   font-size are both expressed as a ratio of --long-form-cell-w (56/44 and
   2.2rem/44px, the box's original proportions at full size) so the digits
   scale down together with the box on a narrow/wide-problem screen instead
   of a shrunk box clipping full-size text. */
.long-form-cell {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--long-form-cell-w, 44px);
  height: calc(var(--long-form-cell-w, 44px) * 56 / 44);
  font-size: calc(2.2rem * var(--long-form-cell-w, 44px) / 44px);
  font-weight: 800;
  flex-shrink: 0;
}

.long-form-operator {
  color: var(--primary);
}

/* Width tracks the row's own cell count (including the operator column) —
   one .long-form-cell width plus its 6px row gap, per column, so the rule
   spans exactly as wide as the columns above it at whatever size
   --long-form-cell-w resolved to for this problem. */
.long-form-rule {
  height: 4px;
  background: var(--text);
  border-radius: 2px;
  width: calc(var(--long-form-width, 3) * (var(--long-form-cell-w, 44px) + 6px));
  margin: 4px 0 8px;
}

.long-form-answer-cell {
  background: var(--bg);
  border: 3px solid var(--primary);
  border-radius: 10px;
}

.long-form-cell-active {
  background: #eaf0ff;
}

/* A filled box is tappable (see longFormSelectCell, app.js) — jump back to
   fix that exact digit rather than backspacing through everything after
   it. cursor:pointer is the only hint on a touch device; :active gives a
   quick press-feedback flash so a tap reads as having registered. */
.long-form-cell-filled {
  cursor: pointer;
}

.long-form-cell-filled:active {
  background: #eaf0ff;
}

/* Carry-over marks — pure scratch space (see longFormCycleCarry, app.js),
   deliberately smaller/quieter than the main problem below it so it reads
   as a working aid, not another required answer. */
.long-form-carry-row {
  margin-bottom: 2px;
}

/* Same --long-form-cell-w-driven scaling as .long-form-cell above (32/44
   and 1.3rem/44px are this box's own original proportions at full size) —
   otherwise a wide problem that shrinks the main cells to fit would leave
   these fixed at 32px, no longer proportioned to match. */
.long-form-carry-cell {
  width: calc(var(--long-form-cell-w, 44px) * 32 / 44);
  height: calc(var(--long-form-cell-w, 44px) * 32 / 44);
  font-size: calc(1.3rem * var(--long-form-cell-w, 44px) / 44px);
  font-weight: 700;
  color: var(--muted);
}

.long-form-carry-tappable {
  cursor: pointer;
  background: var(--bg);
  border: 2px dashed var(--muted);
  border-radius: 8px;
}

.long-form-carry-tappable:active {
  background: #eaf0ff;
}

/* Tapped and waiting for the next keypad digit (see
   longFormSelectCarryCell, app.js) — switches from the quiet dashed
   "scratch space" look to a solid highlight so it's unambiguous which
   column the keypad is about to fill. */
.long-form-carry-cell-active {
  background: #eaf0ff;
  border-style: solid;
  border-color: var(--primary);
  color: var(--text);
}

/* Early Learning's tap-to-match activities (matchColors/matchShapes/
   countingOnes/countingTens — see js/matching.js) — this app's first (and
   only) tap-to-select multiple-choice interaction, everywhere else answers
   by typing. A single reference item up top, 4 large tappable options
   below — sized generously (bigger than .key/.keypad's own touch targets)
   since this section is for a child under 5. */
.matching-reference {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 90px;
  margin: 8px 0 24px;
}

.matching-reference-glyph {
  font-size: 5rem;
  line-height: 1;
}

/* Counting 0-9's quantity reference specifically (renderQuantity,
   js/pictures.js, always loose icons — see the matching-reference-quantity-
   loose comment in matchingReferenceHtml, app.js) — overrides the shared
   .qty-group/.icon rules used elsewhere (Addition/Subtraction's picture
   warm-up, Multiplication's groups, and Counting by Tens' own ten-frame
   bundles) with much bigger icons, and a fixed 5-per-row grid instead of
   flex-wrap. flex-wrap alone let 5-9 icons fit on one unbroken line at
   this container's width, which is exactly what made a bigger count hard
   to count at a glance — 5 columns forces the same "5, then a few more"
   grouping the ten-frame bundles already use, so counting past 5 means
   counting a short, clearly-separated second row instead of a long single
   one. Scoped to -loose, NOT the plain .matching-reference-quantity every
   quantity reference gets, since forcing this same 5-column grid onto
   Counting by Tens' bundles (each already its own 5-column ten-frame)
   squeezed multiple whole bundles into one grid column's width instead of
   leaving them to flex-wrap at their natural size, badly misaligning them. */
.matching-reference-quantity-loose .qty-group {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 10px;
  width: fit-content;
  margin: 0 auto;
}

.matching-reference-quantity-loose .icon {
  font-size: 2.75rem;
  line-height: 1;
}

.matching-options {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 14px;
  width: 320px;
  max-width: 100%;
  margin: 0 auto 16px;
}

.matching-option {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 22px 0;
  border-radius: 16px;
  border: none;
  background: var(--bg);
  cursor: pointer;
}

.matching-option:active {
  transform: scale(0.94);
}

.matching-option-glyph {
  font-size: 2.6rem;
  line-height: 1;
  font-weight: 700;
  color: var(--text);
}

/* Shape glyphs are plain Unicode characters (●■▲★♦♥ — not colored emoji),
   deliberately tinted to one consistent color so shape, not color, is the
   only variable a matchShapes question tests (see MATCHING_SHAPE_PALETTE,
   js/matching.js). Must come after .matching-reference-glyph/
   .matching-option-glyph above in the cascade — both classes land on the
   same element (see matchingReferenceHtml/matchingOptionsHtml, app.js) and
   this one's color needs to win. */
.matching-shape-glyph {
  color: var(--primary);
}

/* A value she's already tapped wrong on THIS problem (matchingEliminatedValues,
   app.js) — greyed out and inert, but still shown in its original grid
   position (not removed) so the layout doesn't jump as she narrows it down. */
.matching-option-eliminated {
  opacity: 0.35;
  cursor: not-allowed;
}

/* "More or Less" (compareObjects/compareNumbers — see
   generateComparisonProblem, js/matching.js, and comparisonPromptHtml/
   comparisonOptionsHtml, app.js). A wrong tap reuses
   .matching-option-eliminated above for its greyed-out state, same as
   every other matching activity. */
.comparison-prompt {
  font-size: 1.3rem;
  color: var(--text);
  margin: 8px 0 20px;
}

.comparison-prompt-word {
  color: var(--primary);
  font-size: 1.6rem;
  font-weight: 700;
}

/* Above & Below's reference object, inline in the question sentence (see
   aboveBelowPromptHtml, app.js) — icon (.stack-icon, same size the stack
   rows below use) and name glued into one inline-flex unit so they wrap
   together as a pair rather than splitting across lines if the sentence
   doesn't fit on one. */
.comparison-prompt-object {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  vertical-align: middle;
}

.comparison-prompt-name {
  font-size: 1.3rem;
  font-weight: 700;
  color: var(--text);
}

.comparison-options {
  display: flex;
  gap: 16px;
  width: 340px;
  max-width: 100%;
  margin: 0 auto 16px;
}

.comparison-option {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 130px;
  padding: 14px 6px;
  border-radius: 18px;
  border: none;
  background: var(--bg);
  cursor: pointer;
  /* A Properties icon (below) can render past its own element's box once
     scaled up — this keeps a large scale factor visually contained inside
     its own panel instead of spilling into the one next to it. */
  overflow: hidden;
}

.comparison-option:active {
  transform: scale(0.95);
}

.comparison-number {
  font-size: 3.5rem;
  font-weight: 700;
  color: var(--text);
  line-height: 1;
}

/* A smaller/tighter grid than .matching-reference-quantity's (which gets
   the whole card's width to itself) — here 2 of these sit side by side, so
   3 columns instead of 5 keeps each icon a comfortable tap-and-count size
   without the pair overflowing a narrow phone screen. */
.comparison-quantity .qty-group {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
  width: fit-content;
  margin: 0 auto;
}

.comparison-quantity .icon {
  font-size: 1.8rem;
  line-height: 1;
}

/* Properties (compareBigSmall/compareLongShort/compareThinThick — see
   comparisonOptionContentHtml, app.js) — a real object emoji, CSS-scaled
   per question via an inline transform (scale/scaleX/scaleY — the one
   thing that actually varies). A fixed base font-size here, scaled up or
   down by that transform, rather than setting font-size directly to a
   target value per question: transform resizes visually without changing
   the element's own box, so .comparison-option's overflow: hidden above
   can reliably keep even a large scale factor inside its own panel. */
.property-icon {
  display: inline-block;
  font-size: 2.75rem;
  line-height: 1;
}

/* "Above & Below" (aboveBelow — see aboveBelowStackHtml, app.js) — 3 rows
   stacked in a column, always in their real top-to-bottom order. The
   reference row (.stack-row-reference, a plain div — see
   generateAboveBelowProblem, js/matching.js) renders the same as the other
   2 rows (.stack-row-option, real <button>s) minus the tap styling, since
   the question text already names/pictures the reference object; a wrong
   tap on one of the option rows reuses .matching-option-eliminated same as
   every other matching activity. .stack-row's own padding/border-radius/
   background deliberately override .btn's pill/padding defaults (both are
   one class each, so source order — this rule comes later — decides it),
   since a .btn styled for the reference div wouldn't apply anyway.
   .stack-icon is also reused (unchanged size) inline in the question
   itself (see .comparison-prompt-object and aboveBelowPromptHtml, app.js)
   so the object she's asked about renders at the exact same size as the 3
   objects in the stack. */
.stack-column {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 320px;
  max-width: 100%;
  margin: 0 auto 16px;
}

.stack-row {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  box-sizing: border-box;
  min-height: 92px;
  padding: 10px 20px;
  border-radius: 16px;
  border: 3px solid transparent;
  background: var(--bg);
}

.stack-row-option {
  cursor: pointer;
}

.stack-icon {
  font-size: 3.5rem;
  line-height: 1;
}

.stack-name {
  flex: 1;
  text-align: left;
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--text);
}


/* Words to Numbers (js/number-words.js) — the word-phrase "question", sized
   like .quiz-problem's own digits (3rem) but as a wrapping block of text
   rather than a single flex row, since a phrase ("nine hundred and
   ninety-nine thousand...") can run far longer than any "a op b =" this app
   has shown before and needs to wrap onto multiple lines instead of
   forcing .quiz-problem's row wider. */
.words-to-numbers-phrase {
  font-size: 2rem;
  font-weight: 800;
  text-align: center;
  line-height: 1.3;
  margin: 4px 0 16px;
  word-break: break-word;
}

/* A labeled <select> row on a card — sits where a level-nav-row's arrows
   would on every other card, but as a real dropdown since stepping through
   10 digit counts (or 3 difficulties) one arrow-tap at a time would be
   slow. Used by wordsToNumbersCardHtml's Digits row and
   numbersInWordsCardHtml's Digits + Difficulty rows (matching the parent's
   own sketch for the Digits dropdown). */
.number-select-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  font-weight: 700;
  margin-bottom: 6px;
}

.number-select-row:last-child {
  margin-bottom: 0;
}

.number-select-row select {
  font-size: 1rem;
  font-weight: 700;
  padding: 6px 10px;
  border-radius: 10px;
  border: 2px solid var(--primary);
  background: var(--bg);
  color: var(--text);
}

/* wordsToNumbersCardHtml's stand-in Difficulty row (see its own comment,
   app.js) — visibility: hidden (not display: none) so it still takes up
   its row's normal height/margin and keeps this card the same height as
   numbersInWordsCardHtml's real Digits+Difficulty card next to it. */
.number-select-row-spacer {
  visibility: hidden;
}

/* Numbers in Words (js/number-words.js) — the answer strip (built phrase so
   far) sits above the tile pool. Fixed min-height so the layout doesn't
   jump between an empty strip (placeholder text) and one with tiles in it;
   dashed border reads as a "drop zone" for the drag-and-drop tiles land on
   (see the dragover/dragstart/drop listeners in app.js). */
.numbers-in-words-answer-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
  align-items: center;
  min-height: 52px;
  padding: 10px;
  margin: 4px 0 16px;
  border: 2px dashed var(--primary);
  border-radius: 12px;
}

.numbers-in-words-strip-placeholder {
  color: var(--muted);
  font-size: 0.9rem;
}

.numbers-in-words-tile-pool {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
}

/* A word chip — pill-shaped rather than .matching-option's square glyph
   tiles, since these are variable-width words, not single glyphs. */
.numbers-in-words-tile {
  font-size: 1.1rem;
  font-weight: 700;
  padding: 8px 16px;
  border-radius: 999px;
  border: 2px solid var(--primary);
  background: var(--bg);
  color: var(--text);
  cursor: pointer;
}

.numbers-in-words-tile:active {
  transform: scale(0.96);
}

.numbers-in-words-tile-used {
  opacity: 0.35;
  cursor: not-allowed;
}

/* Hard difficulty's typed answer box — an uncontrolled <input> (see
   numbersInWordsTypedInputHtml/numbersInWordsSubmitTyped, app.js), styled
   to sit inline with its submit button the same way .answer-box/.key-submit
   pair up in .keypad. */
.numbers-in-words-typed-input {
  font-size: 1.3rem;
  font-weight: 700;
  text-align: center;
  padding: 10px 14px;
  border-radius: 12px;
  border: 2px solid var(--primary);
  background: var(--bg);
  color: var(--text);
  width: 100%;
  max-width: 360px;
}

/* Multiplication Tables worksheet — a bespoke layout, not the one-question
   quiz screen above. Stacked (list above keypad) by default, matching the
   only layout that exists on narrow phones; a wider viewport switches to
   list-left/keypad-right (see the @media block below) — there's no
   existing width-based two-column pattern elsewhere in this file to reuse,
   the quiz screen's own 2-column mode is height/landscape-triggered, not
   width-triggered. */
/* This screen manages its own internal scrolling — header, keypad, and
   Prev/Next stay on screen; only the fact list scrolls — so it opts out of
   .modal-content's generic "whole card scrolls" behavior (overflow:hidden
   here) and lays itself out as a fixed-height flex column instead. */
.tables-modal-content {
  /* Wide enough for .tables-list's own 520px cap (below) plus the fixed
     320px keypad, side by side, with real room to spare — the widest
     possible row ("20 × 20 = 400") was measured at ~409px in one reference
     browser, but that measurement doesn't hold across devices: a tablet
     with a wider default system font for digits clipped "20 × 12 = 240"
     well inside an earlier, more tightly-tuned cap. 520px keeps a large
     margin above the largest reasonable font-metric variance instead of
     chasing another exact pixel count. This modal's padding + gap between
     the two columns eats another ~48px on top of that before the keypad
     even starts. */
  max-width: 910px;
  max-height: 100%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.tables-screen {
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.tables-screen .settings-header {
  flex-shrink: 0;
}

.tables-body {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-top: 12px;
  flex: 1;
  min-height: 0;
}

.tables-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: 1;
  min-height: 0;
  /* Without a cap, flex:1 lets the list (and so the whole popup, via
     .tables-body's flex:1) grow to fill the entire modal max-height —
     showing as many of the 21 rows as fit, all the way to a near-fullscreen
     popup. Capping it here instead sizes the popup to roughly match the
     other three sections' practice popups, with the rest of the rows a
     scroll away rather than stretching the card to the screen's edge. */
  max-height: 40vh;
  overflow-y: auto;
  padding: 4px;
}

/* Empty scroll room above row 0 and below row 20 — height is set from JS
   (see render()) to half the list's own visible height, so the selected
   row can always be scrolled to dead center, even at either end of the
   list where there aren't enough real rows on that side to do it. */
.tables-list-spacer {
  flex-shrink: 0;
}

.tables-row {
  display: flex;
  align-items: center;
  /* flex-start, not space-between: at the larger font below, space-between
     would force the answer out to the row's far edge regardless of content
     width, which is what caused the "0 × 0 =" text to wrap onto two lines
     when the row wasn't that wide — keeping problem+answer close together
     needs far less width. */
  justify-content: flex-start;
  gap: 14px;
  padding: 10px 14px;
  border-radius: 10px;
  background: var(--card-bg);
  border: 2px solid transparent;
  cursor: pointer;
  /* Matches .quiz-problem exactly (the big question display in the other
     three sections) — this is a worksheet of "questions" too, just several
     shown at once instead of one at a time, so the digits should read at
     the same size. */
  font-size: 3rem;
  font-weight: 800;
  color: var(--text);
}

.tables-row-problem {
  white-space: nowrap;
}

.tables-row-mastered {
  background: #e8fbf1;
  color: var(--correct);
}

.tables-row-retesting {
  border-color: var(--incorrect);
}

.tables-row-selected {
  border-color: var(--primary);
}

.tables-row-answer {
  min-width: 48px;
  text-align: center;
}

.tables-row-flash {
  font-size: 1rem;
}

.tables-keypad {
  margin: 0 auto;
  /* .keypad only declares max-width, which is enough in its normal block-
     layout context (the quiz screen) but not as a flex item here — a flex
     item's auto flex-basis falls back to a much smaller intrinsic size for
     a 3-column grid with fr tracks, shrinking every key well below the
     other sections' keypad. An explicit width + flex-shrink:0 forces it to
     always render at that same fixed 320px, never smaller. */
  width: 320px;
  flex-shrink: 0;
}

/* Small — a manual "skip ahead"/"go back" override alongside whatever
   automatic advance-on-mastery already happens, not a gated "you're done"
   action. Shared by the Tables worksheet screen and the other three
   operations' home cards (see .level-nav-row below) — same control, two
   places it's needed. */
.level-nav {
  display: flex;
  justify-content: center;
  gap: 12px;
  margin-top: 16px;
  flex-shrink: 0;
}

/* The home-card variant: arrows flank the level text itself (< Level 3 >)
   instead of sitting in their own row underneath it. */
.level-nav-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
}

/* No circular border/fill here (unlike the feedback bar's own submit
   button) — just the bare arrow glyph, colored via .btn-secondary's own
   color: var(--primary); width/height/padding override .btn-secondary's
   width:100%. */
.level-nav-btn {
  width: 42px;
  height: 42px;
  padding: 0;
  border: none;
  border-radius: 0;
  background: none;
  font-size: 1.4rem;
  font-weight: 900;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Both prev and next render the same "➤" glyph the feedback submit button
   uses (matching it exactly) — prev just mirrors it to point left, rather
   than using a different-shaped character for the two directions. */
.level-nav-btn[data-action$="-prev"] {
  transform: scaleX(-1);
}

/* 960px, not 700px: the real threshold where .tables-list (520px cap) +
   .tables-keypad (fixed 320px, never shrinks) + the gap between them + both
   containers' own padding can all fit side by side without squeezing the
   list below what its widest row needs (888px is the bare minimum — 960px
   leaves real slack rather than landing exactly on the edge). A lower
   breakpoint let the 2-column layout activate before there was actually
   room for it — the list would get compressed under its own cap by the
   keypad's fixed width, clipping wide answers (e.g. "20 × 12 = 240")
   exactly like the too-tight max-width did on its own; this closes that
   in-between zone entirely rather than re-measuring where it starts. */
@media (min-width: 960px) {
  .tables-body {
    flex-direction: row;
    /* Default (stretch), not flex-start — .tables-list needs the row's
       full height to know how much space it has to scroll within; sticky
       positioning on the keypad is no longer needed for it to stay in view
       now that the outer modal doesn't scroll at all (see
       .tables-modal-content), only .tables-list does. */
  }
  .tables-list {
    flex: 1;
    /* The widest rows — a 2-digit table times a 2-digit b, e.g.
       "16 × 11 = 176" or "20 × 20 = 400" — were measured at ~409px in one
       reference browser and given a 440px cap on that basis, but a
       system-font substitution on another device (seen on a tablet:
       "20 × 12 = 240" clipped to "24") rendered the same digits wider than
       that measurement assumed. 520px is deliberately well past any single
       measured worst case, to absorb a real amount of cross-device/font
       variance rather than exactly matching one browser's numbers again. */
    max-width: 520px;
  }
  .tables-keypad {
    margin: 0;
    /* Opt out of the row's stretch (above) — without this the keypad
       matches .tables-list's full height, spacing its button rows out with
       large gaps instead of sitting at its own compact, natural size. */
    align-self: flex-start;
  }
}

/* Pictures */
.qty-group {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 4px;
  align-items: center;
  justify-content: center;
}

.icon {
  font-size: 1.6rem;
}

.icon-taken {
  opacity: 0.25;
  filter: grayscale(1);
}

.icon-empty {
  font-size: 1.2rem;
  color: var(--muted);
}

.icon-blank {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.6rem;
  height: 1.6rem;
  border: 2px dashed var(--muted);
  border-radius: 6px;
  font-size: 1rem;
  line-height: 1;
  color: var(--muted);
  opacity: 0.75;
}

.bundle {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  background: #fff6e0;
  border: 2px dashed #e0c060;
  border-radius: 10px;
  padding: 6px 8px 4px;
  margin: 2px;
}

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

.bundle-icon {
  font-size: 1rem;
}

.bundle-badge {
  display: block;
  font-size: 0.65rem;
  color: var(--muted);
  text-align: center;
  margin-top: 2px;
}

.picture-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
}

.picture-subtract .icon {
  transition: opacity 0.2s ease;
}

.picture-caption {
  font-size: 0.8rem;
  color: var(--muted);
  margin-top: 6px;
}

.picture-groups {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  justify-content: center;
}

.group {
  border: 2px solid #eee;
  border-radius: 10px;
  padding: 6px;
}

.group-more {
  font-size: 0.85rem;
  color: var(--muted);
  align-self: center;
}

/* Summary screen */
.summary-screen h1 {
  text-align: center;
}

.summary-row {
  background: var(--card-bg);
  border-radius: var(--border-radius);
  padding: 20px;
  margin-bottom: 18px;
  box-shadow: 0 3px 12px rgba(0,0,0,0.08);
}

.summary-stats {
  display: flex;
  gap: 16px;
  color: var(--muted);
  margin: 8px 0;
  flex-wrap: wrap;
}

.summary-level {
  margin-bottom: 10px;
  font-weight: 600;
}

/* Details screen */
.details-tabs {
  display: flex;
  justify-content: center;
  gap: 8px;
  margin-bottom: 14px;
  flex-wrap: wrap;
}

.details-tab {
  font-family: inherit;
  font-size: 0.95rem;
  font-weight: 700;
  padding: 8px 16px;
  border-radius: 999px;
  border: 2px solid var(--primary);
  background: white;
  color: var(--primary);
  cursor: pointer;
}

.details-tab.active {
  background: var(--primary);
  color: white;
}

.details-average {
  text-align: center;
  color: var(--text);
  font-size: 0.95rem;
  margin-bottom: 4px;
}

.details-summary {
  text-align: center;
  color: var(--muted);
  margin-bottom: 12px;
}

.btn-download-excel {
  display: block;
  margin: 0 auto 16px;
  color: var(--primary);
}

.details-filters {
  display: flex;
  justify-content: center;
  gap: 18px;
  margin-bottom: 16px;
  color: var(--muted);
  font-size: 0.9rem;
}

.details-filters label {
  display: flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
}

/* Same idea as the Tables worksheet and Reset Progress — title, tabs,
   average/summary stats, the Excel download button, and the status filters
   all stay fixed (she needs those reachable without scrolling back up);
   only the actual fact table — the part that genuinely grows long —
   scrolls inside itself. */
.details-modal-content {
  max-height: 100%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.details-screen {
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.details-screen > *:not(.details-table-wrap) {
  flex-shrink: 0;
}

.details-table-wrap {
  background: var(--card-bg);
  border-radius: var(--border-radius);
  box-shadow: 0 3px 12px rgba(0, 0, 0, 0.08);
  overflow-x: auto;
  overflow-y: auto;
  flex: 1;
  min-height: 0;
  margin-bottom: 20px;
}

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

.details-table th {
  position: sticky;
  top: 0;
  background: var(--card-bg);
  text-align: left;
  padding: 10px 12px;
  border-bottom: 2px solid var(--bg);
  color: var(--muted);
}

.details-table td {
  padding: 8px 12px;
  border-bottom: 1px solid var(--bg);
}

/* The rest of the table is short, fixed-shape values that read best kept
   to one line (the table already scrolls horizontally for that) — the
   History cell is real prose, so it gets to wrap within a fixed-ish width
   instead of forcing the whole row absurdly wide. */
.details-history-cell {
  white-space: normal;
  min-width: 200px;
  max-width: 280px;
  color: var(--muted);
}

.details-row-mastered td:nth-child(3) {
  color: var(--correct);
  font-weight: 700;
}

.details-row-retesting td:nth-child(3) {
  color: var(--incorrect);
  font-weight: 700;
}

/* A mastered fact's best time vs. its level's average (see
   speedVsAverage in mastery.js) — faster-than-average colored the same
   green as "mastered" (it's the good direction), same-as-average left
   neutral. Slower-than-average splits into two bands matching the "2x
   average = slow" mastery rule: amber up to 2x (still fine for now, but
   worth watching), red at 2x+ (the exact point a fact would actually get
   demoted back to retesting), same red as "retesting" elsewhere. */
.speed-below {
  color: var(--correct);
}

.speed-above {
  color: #d99a1b;
}

.speed-far-above {
  color: var(--incorrect);
}

.speed-same {
  color: var(--muted);
}

.details-empty {
  text-align: center;
  color: var(--muted);
  padding: 24px;
}

@media (max-width: 480px) {
  :root {
    font-size: 16px;
  }
  .quiz-problem {
    font-size: 2.2rem;
    gap: 10px;
  }
  .tables-row {
    font-size: 2.2rem;
  }
  .details-table {
    font-size: 0.75rem;
  }

  /* The practice popup is the tallest screen in the app — tighten every bit
     of vertical chrome so a typical phone can fit it without scrolling. */
  .modal-overlay {
    padding: 4px;
  }
  .modal-content {
    padding: 10px 8px 12px;
  }
  .quiz-screen {
    padding: 10px;
  }
  .quiz-progress {
    margin: 12px 0 8px;
  }
  .quiz-pictures {
    margin-bottom: 6px;
  }
  .answer-box {
    min-height: 56px;
  }
  .icon {
    font-size: 1rem;
  }
  .picture-row {
    gap: 6px;
  }
  .qty-group {
    gap: 1px;
  }
  /* Multiplication shows up to 6 groups (see maxGroups in pictures.js) — at
     this width, a wide group (8-9 icons) only fits 1-per-row, forcing 6
     stacked rows no matter how small the icons get. A fixed 3-column grid
     keeps it to 2 rows of groups instead, letting each group's own icons
     wrap internally (2 short lines) rather than the whole layout stacking
     into 6 tall ones. */
  .picture-groups {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 2px;
  }
  .group {
    padding: 1px;
    border-width: 1px;
    width: auto;
  }
  .group .qty-group {
    justify-content: center;
  }
  .group .icon {
    font-size: 0.75rem;
  }
  .bundle-icon {
    font-size: 0.7rem;
  }
  .group-more {
    grid-column: 1 / -1;
    font-size: 0.65rem;
    line-height: 1.1;
  }
  .feedback-indicator {
    height: 32px;
    font-size: 2rem;
    margin-bottom: 4px;
  }
  .keypad {
    gap: 6px;
    margin: 0 auto 8px;
  }
  .key {
    padding: 10px 0;
    font-size: 1.3rem;
  }
  .quiz-footer-actions {
    margin-top: 6px;
  }
  .progress-bar {
    height: 14px;
  }
  .progress-pointer {
    top: -20px;
    font-size: 0.7rem;
    padding: 1px 5px;
  }
}

/* Any short viewport — phone landscape (wide but only ~320-430px tall) or
   the rare very-small portrait phone. Stacking everything in one column
   (like normal/portrait mobile does) can't fit in this little height no
   matter how much padding is trimmed, so the quiz screen switches to a
   two-column grid instead: info+problem on the left, keypad on the right.
   Grid areas are assigned by class below, so this needs no HTML changes —
   unused areas (e.g. "paused") are simply left empty when not in the DOM. */
@media (max-height: 500px) {
  .modal-overlay {
    padding: 2px;
    align-items: center;
  }
  .modal-content {
    padding: 4px;
    max-width: 900px;
    border-radius: 10px;
  }
  .quiz-screen {
    padding: 10px 8px 6px;
    border-radius: 10px;
  }
  .quiz-header {
    font-size: 1rem;
  }
  .quiz-level div:nth-child(2),
  .quiz-level div:nth-child(3) {
    display: none;
  }
  .quiz-timing,
  .quiz-progress,
  .quiz-start-time {
    display: none;
  }
}

/* Narrow-AND-somewhat-short phones (e.g. the original iPhone SE at
   320x568) fall outside the max-height:500 tier above but can still be a
   few pixels short once picture-heavy problems wrap to two rows — same
   trims, wider height allowance, but width-gated so it never touches the
   already-comfortable 375x667/390x844-class phones. */
@media (max-width: 480px) and (max-height: 650px) {
  .quiz-level div:nth-child(2),
  .quiz-level div:nth-child(3) {
    display: none;
  }
  .quiz-timing,
  .quiz-progress,
  .quiz-start-time {
    display: none;
  }
}

@media (max-height: 500px) and (orientation: landscape) {
  /* Left column (header/level/pictures/problem/footer) auto-stacks in
     document order, one per row, just by being pinned to column 1 with no
     explicit row — the browser assigns each the next free row itself, so
     this doesn't need to hardcode how many rows pictures do or don't add.
     The keypad is pinned to column 2 spanning every row that creates, and
     centers itself vertically alongside whatever height that ends up being. */
  .quiz-screen {
    display: grid;
    grid-template-columns: 1fr auto;
    column-gap: 10px;
    align-items: start;
    text-align: left;
  }
  .quiz-header {
    font-size: 1rem;
  }
  .quiz-header,
  .quiz-pictures,
  .quiz-problem,
  .quiz-paused,
  .quiz-footer-actions {
    grid-column: 1;
  }
  .quiz-pictures {
    margin: 2px 0;
    max-height: 44px;
    overflow: hidden;
  }
  .icon {
    font-size: 1rem;
  }
  .quiz-problem {
    justify-content: flex-start;
    font-size: 1.5rem;
    margin: 2px 0;
    gap: 8px;
  }
  .feedback-indicator {
    display: none;
  }
  .keypad {
    grid-column: 2;
    grid-row: 1 / -1;
    align-self: center;
    max-width: 200px;
    gap: 3px;
    margin: 0;
  }
  .key {
    padding: 3px 0;
    font-size: 1rem;
  }
  .quiz-footer-actions {
    margin-top: 2px;
    justify-content: flex-start;
    gap: 10px;
  }
  .btn-footer-icon {
    width: 30px;
    height: 30px;
    font-size: 0.9rem;
  }
  .quiz-footer-actions .level-nav-btn {
    width: 30px;
    height: 30px;
    font-size: 1.1rem;
  }
  .answer-box {
    min-height: 34px;
    min-width: 70px;
    padding: 2px 8px;
  }
}
