/* =====================================================
   game-modes.css
   PURPOSE: Styles for the Game Modes tab and every screen
   pushed from it, across all THREE game modes: Quiz (deck
   picker, gameplay, results), Memory Match (deck picker,
   gameplay, round-complete, results), and Type the Answer
   (gameplay, results — it SHARES Quiz's deck picker, see
   renderQuizDeckSelect()'s jsdoc in game-modes.js, so there's
   no separate #type-deck-select-screen at all).

   SCOPE: Everything inside #game-modes-screen,
   #quiz-deck-select-screen, #quiz-play-screen,
   #match-deck-select-screen, #match-play-screen, and
   #type-play-screen. Deliberately self-contained — does NOT
   reuse deck.css's .deck-view__header or study.css's
   .study-header/.study-progress-*/.study-complete* classes,
   even though they'd look almost identical, because those
   files are scoped to their own screens (see each file's own
   SCOPE note) and reusing their bare class names here would
   silently couple this file to unrelated screens — the
   exact kind of cross-screen leak that broke .btn--shuffle
   once before. DO NOT put styles for other screens here.
   For the same reason, Match's and Type the Answer's own
   classes below (.match-*, .type-*) are each their OWN
   parallel set, not a reuse of .quiz-*, even where a mode
   looks near-identical to Quiz — see .match-header below for
   exactly this situation. (Type the Answer's deck-select
   markup is the one deliberate exception — it's the literal
   SAME rendered HTML as Quiz's, not just similar-looking, so
   .quiz-deck-item/.quiz-header/etc. genuinely apply to both;
   only its GAMEPLAY screen needed its own .type-* set.) */

#game-modes-screen {
  display:        flex;
  flex-direction: column;
  gap:            var(--space-4);
}

/* --- Game mode menu --- */
.game-mode-list {
  display:        flex;
  flex-direction: column;
  gap:            var(--space-3);
}

.game-mode-card {
  display:          flex;
  align-items:      center;
  gap:              var(--space-3);
  padding:          var(--space-4);
  background-color: var(--color-card-bg);
  border:           none;
  border-radius:    var(--radius-lg);
  box-shadow:       var(--shadow-elevation-1);
  color:            var(--color-text-primary);
  font-family:      var(--font-primary);
  text-align:       left;
  cursor:           pointer;
  transition:        box-shadow 0.2s ease, transform 0.15s ease;
}

.game-mode-card:hover {
  box-shadow: var(--shadow-elevation-2);
  transform:  translateY(-1px);
}

.game-mode-card:active {
  transform: scale(0.98);
}

.game-mode-card__icon {
  display:          flex;
  align-items:      center;
  justify-content:  center;
  flex-shrink:      0;
  width:            44px;
  height:           44px;
  border-radius:    50%;
  background-color: var(--tint-accent-soft);
  color:            var(--color-accent-amber);
}

.game-mode-card__text {
  flex:           1;
  min-width:      0;
  display:        flex;
  flex-direction: column;
  gap:            2px;
}

.game-mode-card__name {
  font-size:   var(--font-size-body);
  font-weight: 600;
}

.game-mode-card__description {
  font-size: var(--font-size-footnote);
  color:     var(--color-text-secondary);
}

.game-mode-card__chevron {
  flex-shrink: 0;
  color:       var(--color-text-secondary);
}


/* --- Shared quiz header (deck picker + gameplay + results) --- */
#quiz-deck-select-screen,
#quiz-play-screen {
  display:        flex;
  flex-direction: column;
  gap:            var(--space-4);
}

/* Overrides animations.css's shared "#screen-container > *"
   entrance animation with an opacity-only version for JUST
   this screen (not #quiz-play-screen above — no position:fixed
   descendant there) — same fix, same reasoning as scheduler.css's
   identical override (see its own longer comment): the shared
   transform-based animation creates a new containing block for
   any position:fixed descendant while it's running, and
   .quiz-deck-select__start (further down) is exactly that. This
   one screen is shared by BOTH Quiz and Type the Answer's deck
   pickers (renderQuizDeckSelect() in game-modes.js, keyed by
   params.modeId), so this single override covers both. Two IDs
   (not a bare "#quiz-deck-select-screen" selector) to reliably
   out-specificity the shared rule regardless of the two files'
   <link> order in index.html. */
#screen-container > #quiz-deck-select-screen {
  animation: fadeIn 0.2s cubic-bezier(0.25, 0.1, 0.25, 1);
}

/* #quiz-play-screen specifically also needs a definite
   height (not just auto-sized to its content) — otherwise
   .quiz-complete's flex: 1 has nothing to grow into, and
   its "margin-top: auto" trick for anchoring the Play
   Again/Back to Game Modes buttons to the bottom of the
   screen has no extra space to push into either, leaving
   them stranded right under the score with a dead gap
   below. 100% (not 100vh) fills exactly the space
   #screen-container has available, same reasoning as
   #study-mode-screen's identical rule in study.css. */
#quiz-play-screen {
  height: 100%;
}

/* Grid (not flex) so the title is TRULY centered regardless
   of what's in the flanking slots — a Back button on the
   left and, depending on the screen, a running score on the
   right, or nothing on either side at all. Two equal 1fr
   side columns plus an explicit grid-column: 2 on the title
   (below) keeps it centered on the full row even when only
   one side has content (e.g. just a title, no Back button,
   on the Quiz Complete screen). */
.quiz-header {
  display:               grid;
  grid-template-columns: 1fr auto 1fr;
  align-items:           center;
  gap:                   var(--space-3);
  padding-bottom:        var(--space-3);
  border-bottom:         var(--border-width) solid var(--color-border);
}

/* justify-self: start — CSS Grid's default (justify-items:
   stretch) would otherwise stretch this button to fill the
   ENTIRE left column (buttons have width: auto, which stretch
   applies to), and since .btn itself is
   justify-content: center internally, the "← Back" label would
   end up centered in that stretched-wide button instead of
   hugging the actual left edge — same fix applied to
   .match-header/.type-header below and .deck-view__header in
   deck.css. */
.quiz-header .btn--back {
  justify-self: start;
}

.quiz-header__title {
  grid-column:   2;
  font-size:     var(--font-size-title3);
  font-weight:   700;
  color:         var(--color-text-primary);
  min-width:     0;
  text-align:    center;
  overflow:      hidden;
  text-overflow: ellipsis;
  white-space:   nowrap;
}

/* Running score, top-right of the gameplay header */
.quiz-score {
  justify-self:     end;
  display:          flex;
  align-items:      center;
  gap:              4px;
  flex-shrink:      0;
  padding:          4px 10px;
  border-radius:    999px;
  background-color: var(--tint-accent-soft);
  color:            var(--color-accent-amber);
  font-size:        var(--font-size-footnote);
  font-weight:      700;
}


/* --- Deck picker: search toggle (header, top-right) --- */
.quiz-deck-search-toggle {
  justify-self:     end;
  display:          flex;
  align-items:      center;
  justify-content:  center;
  flex-shrink:      0;
  width:            32px;
  height:           32px;
  border:           none;
  border-radius:    50%;
  background-color: var(--ios-tertiarySystemFill);
  color:            var(--color-accent-amber);
  cursor:           pointer;
  transition:        background-color 0.15s ease, transform 0.1s ease;
}

.quiz-deck-search-toggle:hover {
  background-color: var(--ios-secondarySystemFill);
}

.quiz-deck-search-toggle:active {
  transform: scale(0.92);
}

/* Search field — same pill pattern as Home's deck search
   (styles/home.css .deck-search) and Deck View's card search
   (styles/deck.css .deck-view-search), duplicated here rather
   than shared since this file is scoped to its own screens
   (see the SCOPE note at the top of this file). */
.quiz-deck-search {
  display:          flex;
  align-items:      center;
  gap:              6px;
  padding:          7px 10px;
  background-color: var(--ios-tertiarySystemFill);
  border-radius:    999px;
}

.quiz-deck-search__icon {
  display:     flex;
  flex-shrink: 0;
  color:       var(--color-text-secondary);
}

.quiz-deck-search__input {
  flex:        1;
  min-width:   0;
  background:  transparent;
  border:      none;
  color:       var(--color-text-primary);
  font-size:   var(--font-size-footnote);
  font-family: var(--font-primary);
  outline:     none;
}

.quiz-deck-search__input::placeholder {
  color: var(--color-text-secondary);
}

.quiz-deck-search__clear {
  display:          flex;
  align-items:      center;
  justify-content:  center;
  flex-shrink:      0;
  width:            18px;
  height:           18px;
  padding:          0;
  border:           none;
  border-radius:    50%;
  background-color: var(--ios-systemGray3);
  color:            #fff;
  cursor:           pointer;
}


/* --- Deck picker list --- */
.quiz-deck-list {
  display:        flex;
  flex-direction: column;
  background-color: var(--color-card-bg);
  border-radius:  var(--radius-lg);
  box-shadow:     var(--shadow-elevation-1);
  overflow:       hidden;
}

.quiz-deck-item {
  position:      relative;
  /* relative = the containing block for .quiz-deck-item__check
     below, which centers itself over the whole row. */
  display:       flex;
  align-items:   center;
  gap:           var(--space-3);
  padding:       var(--space-3) var(--space-4);
  border:        none;
  border-bottom: var(--border-width) solid var(--color-border);
  background:    transparent;
  color:         var(--color-text-primary);
  font-family:   var(--font-primary);
  text-align:    left;
  cursor:        pointer;
  transition:     background-color 0.15s ease;
}

.quiz-deck-list .quiz-deck-item:last-child {
  border-bottom: none;
}

.quiz-deck-item:not(:disabled):hover {
  background-color: var(--ios-tertiarySystemFill);
}

.quiz-deck-item:not(:disabled):active {
  background-color: var(--ios-secondarySystemFill);
}

.quiz-deck-item--disabled {
  opacity: 0.45;
  cursor:  not-allowed;
}

/* Selected deck row — tinted background, plus the centered
   checkmark badge below becomes visible. */
.quiz-deck-item--selected {
  background-color: var(--tint-accent-soft);
}

/* Checkmark badge — always in the markup (see
   renderQuizDeckListHTML() in game-modes.js) but hidden by
   default, shown only on a selected row. Centered over the
   WHOLE row (not a side checkbox) per how this was asked
   for, with its own solid background + shadow so it reads
   clearly on top of the row's icon/text regardless of what's
   underneath it. */
.quiz-deck-item__check {
  display:          none;
  position:         absolute;
  left:             50%;
  top:              50%;
  transform:        translate(-50%, -50%);
  align-items:      center;
  justify-content:  center;
  width:            34px;
  height:           34px;
  border-radius:    50%;
  background-color: var(--color-accent-amber);
  color:            #fff;
  box-shadow:       var(--shadow-elevation-2);
}

.quiz-deck-item--selected .quiz-deck-item__check {
  display: flex;
}

.quiz-deck-item__icon {
  display:          flex;
  align-items:      center;
  justify-content:  center;
  flex-shrink:      0;
  width:            34px;
  height:           34px;
  border-radius:    50%;
  background-color: var(--tint-accent-soft);
  color:            var(--color-accent-amber);
}

.quiz-deck-item__info {
  flex:           1;
  min-width:      0;
  display:        flex;
  flex-direction: column;
  gap:            2px;
}

.quiz-deck-item__name {
  font-size:     var(--font-size-body);
  overflow:      hidden;
  text-overflow: ellipsis;
  white-space:   nowrap;
}

.quiz-deck-item__caption {
  font-size: var(--font-size-footnote);
  color:     var(--color-text-secondary);
}

/* "Start Quiz (N decks)" — only shown in select mode once
   at least one deck is checked. Disabled (with an
   explanatory label swapped in via JS — see
   updateQuizStartButton() in game-modes.js) until the
   combined selection has enough usable cards.
   Floats above the deck list at a fixed screen position,
   same pattern as Home's "+" FAB (styles/home.css .home-fab)
   — centered, elevated, always visible regardless of scroll
   position, rather than living in normal document flow where
   scrolling past it (or a short list not reaching it) could
   hide it. Width matches the FAB's own containing-block
   reasoning (percentage of <body>, which is deliberately
   sized to the "phone frame" on desktop — see main.css) but
   spans the row as a pill instead of a circle, since this
   button needs room for a text label. */
.quiz-deck-select__start {
  position:      fixed;
  left:          50%;
  bottom:        calc(var(--bottom-nav-height) + var(--safe-area-bottom) + 16px);
  transform:     translateX(-50%);
  width:         calc(100% - 32px);
  max-width:     400px;
  box-shadow:    var(--shadow-elevation-2);
  z-index:       150;
  /* Between the header (100) and bottom nav (200) — same
     layer the FABs use, for the same reason: it visually
     sits between those two bars. */

  /* FORCE a single line. The disabled-state label (see
     updateQuizStartButton() in game-modes.js) is dynamic
     text like "Need 3 more cards — select another deck",
     long enough to wrap on a narrower phone — and since this
     button is fixed with only "bottom" anchored, wrapping to
     2 lines makes it grow TALLER UPWARD, past the fixed
     76px .quiz-deck-select-content-spacer reserves for it
     below the deck list. At z-index 150 it would then sit on
     top of the last deck row(s), silently swallowing any tap
     meant for that row instead of the button — which reads
     exactly like "the deck I tried to add never got
     selected," worse with 2+ decks since the button is only
     even visible (and so only able to overlap anything) once
     the first deck is already picked.
     text-overflow ellipsis keeps the rare case where a longer
     message still can't fit contained within the pill, rather
     than spilling text outside its rounded corners. */
  white-space:   nowrap;
  overflow:      hidden;
  text-overflow: ellipsis;
}

/* Solid (not faded) disabled state — a translucent/opacity-
   dimmed button was hard to read floating over the deck
   list, so this swaps to a plain muted fill instead of
   lowering opacity, keeping the label fully legible while
   still reading clearly as "not ready yet". */
.quiz-deck-select__start:disabled {
  background-color: var(--ios-systemGray4);
  color:             var(--color-text-secondary);
  cursor:            not-allowed;
}

/* Reserves room at the bottom of the deck list so the last
   row or two isn't hidden behind the floating button above
   — harmless in normal (non-select) mode too, where the
   button is just hidden and this is a bit of unused scroll
   space instead.
   Deliberately reuses the SAME tokens as .quiz-deck-select__
   start's own "bottom" offset above, rather than a plain
   flat px guess — a flat number that isn't actually derived
   from the button's own position formula can silently drift
   out of sync with it (which is exactly what happened here:
   the previous flat 76px covered the button's bottom offset
   but never accounted for the button's OWN rendered height on
   top of that, under-reserving by ~38px). The extra 56px
   below covers the button's real height (~44px, a padding:
   10px 18px pill around one line of --font-size-body text)
   plus a little breathing room above it — without this, that
   last ~38px is silently eaten out of the LAST DECK ROW
   itself once the list is scrolled all the way down (which
   only happens once there are enough decks to need scrolling
   — i.e. exactly "select several decks"), covering that row
   with the button and swallowing any tap meant for it. */
.quiz-deck-select-content-spacer {
  height: calc(var(--bottom-nav-height) + var(--safe-area-bottom) + 16px + 56px);
}


/* --- Gameplay: progress row --- */
.quiz-progress-row {
  display:        flex;
  flex-direction: column;
  gap:            6px;
}

.quiz-progress-bar-wrap {
  height:           6px;
  border-radius:    999px;
  background-color: var(--ios-tertiarySystemFill);
  overflow:         hidden;
}

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

.quiz-progress-counter {
  font-size: var(--font-size-footnote);
  color:     var(--color-text-secondary);
  text-align: center;
}


/* --- Gameplay: question card --- */
.quiz-question-card {
  display:          flex;
  align-items:      center;
  justify-content:  center;
  min-height:       120px;
  padding:          var(--space-5);
  background-color: var(--color-card-bg);
  border-radius:    var(--radius-lg);
  box-shadow:       var(--shadow-elevation-1);
  text-align:       center;
}

.quiz-question-card__text {
  font-size:   var(--font-size-title3);
  font-weight: 600;
  color:       var(--color-text-primary);
  line-height: 1.4;
}

/* "Always White Flashcards" Appearance setting (Profile →
   theme-manager.js's applyWhiteCards()) — same reasoning as
   study.css's :root[data-white-cards="true"] .study-card-face
   rule (see its comment there for the full explanation).
   Pins JUST the flashcard-content surface — the question card
   here, the 4 answer options further down, and Memory Match's
   revealed tile face (see .match-tile__face--front below) —
   not the surrounding screen chrome (header, buttons), same
   scoping the other two screens already use.
   Safe to also set the literal background-color directly
   here (not just the token) since nothing else ever overrides
   .quiz-question-card's own background — unlike .quiz-option
   right below, which needs the token-only version. */
:root[data-white-cards="true"] .quiz-question-card {
  background-color:     #FFFFFF;
  --color-card-bg:      #FFFFFF;
  --color-text-primary: #000000;
}


/* --- Gameplay: answer options --- */
.quiz-options {
  display:        flex;
  flex-direction: column;
  gap:            var(--space-3);
}

.quiz-option {
  padding:          var(--space-3) var(--space-4);
  background-color: var(--color-card-bg);
  border:           2px solid transparent;
  border-radius:    var(--border-radius);
  box-shadow:       var(--shadow-elevation-1);
  color:            var(--color-text-primary);
  font-size:        var(--font-size-body);
  font-family:      var(--font-primary);
  text-align:       left;
  cursor:           pointer;
  transition:        background-color 0.15s ease,
                     border-color     0.15s ease,
                     transform        0.1s ease;
}

.quiz-option:not(:disabled):hover {
  background-color: var(--ios-tertiarySystemFill);
}

.quiz-option:not(:disabled):active {
  transform: scale(0.98);
}

.quiz-option:disabled {
  cursor: default;
}

/* "Always White Flashcards" — TOKEN-ONLY version (no literal
   background-color/color set directly, unlike
   .quiz-question-card above). .quiz-option--correct/--wrong
   below derive their own tinted background from color-mix(...,
   var(--color-card-bg)) and set color directly to the
   semantic green/red accent rather than --color-text-primary —
   setting a literal background-color/color here would have
   HIGHER specificity than those single-class variant selectors
   and silently override their correct/wrong feedback color
   outright. Overriding just the tokens lets the base .quiz-
   option (which DOES read them) go white/black normally, while
   --correct/--wrong's own color-mix() naturally picks up the
   new white base too — a lightly green/red-tinted WHITE
   instead of tinted dark, correct feedback fully intact. */
:root[data-white-cards="true"] .quiz-option {
  --color-card-bg:      #FFFFFF;
  --color-text-primary: #000000;
}

/* Correct answer — always highlighted green once the
   question is answered, whether or not it was the one
   picked, so the right answer is always visible. */
.quiz-option--correct {
  background-color: color-mix(in srgb, var(--ios-systemGreen) 18%, var(--color-card-bg));
  border-color:      var(--ios-systemGreen);
  color:             var(--ios-systemGreen);
  font-weight:       700;
}

/* The picked option, only when it was wrong (the correct
   one already gets --correct above, so this only ever
   applies to a second, different button). */
.quiz-option--wrong {
  background-color: color-mix(in srgb, var(--ios-systemRed) 14%, var(--color-card-bg));
  border-color:      var(--ios-systemRed);
  color:             var(--ios-systemRed);
}

.quiz-next-btn {
  width: 100%;
}


/* --- Quiz Complete --- */
.quiz-complete {
  display:         flex;
  flex-direction:  column;
  align-items:     center;
  justify-content: flex-start;
  flex:            1;
  gap:             10px;
  padding:         2rem 1.5rem;
  text-align:      center;
}

.quiz-complete__emoji {
  font-size:     56px;
  line-height:   1;
  margin-bottom: 6px;
}

.quiz-complete__title {
  font-size:   var(--font-size-title2);
  font-weight: 700;
  color:       var(--color-text-primary);
}

.quiz-complete__subtitle {
  font-size:     var(--font-size-body);
  color:         var(--color-text-secondary);
  max-width:     280px;
  line-height:   1.5;
  margin-bottom: 8px;
}

.quiz-complete__subtitle strong {
  color: var(--color-text-primary);
}

.quiz-complete__again,
.quiz-complete__done {
  width:     100%;
  max-width: 320px;
}

.quiz-complete__again {
  /* Auto top margin absorbs all remaining vertical space in
     the flex column above it, pushing both buttons down to
     the bottom of the screen instead of sitting centered
     with the emoji/title/score circles. */
  margin-top:    auto;
  margin-bottom: 10px;
}

.quiz-complete__done {
  background-color: var(--ios-tertiarySystemFill);
  color:             var(--color-text-primary);
}

.quiz-complete__done:hover {
  background-color: var(--ios-secondarySystemFill);
}


/* ═══════════════════════════════════════════════════════
   MEMORY MATCH
   Own parallel set of classes, not a reuse of .quiz-* —
   see this file's top SCOPE note for why, even where the
   shape is near-identical to Quiz (e.g. .match-header below
   vs .quiz-header above).
   ═══════════════════════════════════════════════════════ */

#match-deck-select-screen,
#match-play-screen {
  display:        flex;
  flex-direction: column;
  gap:            var(--space-4);
}

/* Needs a definite height for the same reason as
   #quiz-play-screen above — .match-complete's flex: 1 and
   its "margin-top: auto" button-anchoring trick both need
   real space to grow/push into. */
#match-play-screen {
  height: 100%;
}

/* Same 3-column grid-centered title as .quiz-header — see
   its own comment above for why grid (not flex) is used. */
.match-header {
  display:               grid;
  grid-template-columns: 1fr auto 1fr;
  align-items:           center;
  gap:                   var(--space-3);
  padding-bottom:        var(--space-3);
  border-bottom:         var(--border-width) solid var(--color-border);
}

/* justify-self: start — see .quiz-header .btn--back's identical
   comment above for why this is needed. */
.match-header .btn--back {
  justify-self: start;
}

.match-header__title {
  grid-column:   2;
  font-size:     var(--font-size-title3);
  font-weight:   700;
  color:         var(--color-text-primary);
  min-width:     0;
  text-align:    center;
  overflow:      hidden;
  text-overflow: ellipsis;
  white-space:   nowrap;
}

/* "Round 2/3", top-right of the gameplay header — only
   rendered at all once a deck actually needs more than one
   round (see renderMatchRound() in game-modes.js). */
.match-header__round {
  justify-self: end;
  flex-shrink:  0;
  font-size:    var(--font-size-footnote);
  font-weight:  600;
  color:        var(--color-text-secondary);
}

.match-deck-name {
  font-size: var(--font-size-footnote);
  color:     var(--color-text-secondary);
  text-align: center;
}


/* --- Deck picker list --- */
.match-deck-list {
  display:        flex;
  flex-direction: column;
  background-color: var(--color-card-bg);
  border-radius:  var(--radius-lg);
  box-shadow:     var(--shadow-elevation-1);
  overflow:       hidden;
}

.match-deck-item {
  display:       flex;
  align-items:   center;
  gap:           var(--space-3);
  padding:       var(--space-3) var(--space-4);
  border:        none;
  border-bottom: var(--border-width) solid var(--color-border);
  background:    transparent;
  color:         var(--color-text-primary);
  font-family:   var(--font-primary);
  text-align:    left;
  cursor:        pointer;
  transition:     background-color 0.15s ease;
}

.match-deck-list .match-deck-item:last-child {
  border-bottom: none;
}

.match-deck-item:not(:disabled):hover {
  background-color: var(--ios-tertiarySystemFill);
}

.match-deck-item:not(:disabled):active {
  background-color: var(--ios-secondarySystemFill);
}

.match-deck-item--disabled {
  opacity: 0.45;
  cursor:  not-allowed;
}

.match-deck-item__icon {
  display:          flex;
  align-items:      center;
  justify-content:  center;
  flex-shrink:      0;
  width:            34px;
  height:           34px;
  border-radius:    50%;
  background-color: var(--tint-accent-soft);
  color:            var(--color-accent-amber);
}

.match-deck-item__info {
  flex:           1;
  min-width:      0;
  display:        flex;
  flex-direction: column;
  gap:            2px;
}

.match-deck-item__name {
  font-size:     var(--font-size-body);
  overflow:      hidden;
  text-overflow: ellipsis;
  white-space:   nowrap;
}

.match-deck-item__caption {
  font-size: var(--font-size-footnote);
  color:     var(--color-text-secondary);
}

.match-deck-item__chevron {
  flex-shrink: 0;
  color:       var(--color-text-secondary);
}


/* --- Gameplay: tile grid --- */
/* 2 columns (not 4) — with 8 tiles that's 4 rows of 2, wide
   enough on a phone for a full line of card text to actually
   fit before .match-tile__text's own scroll kicks in. */
.match-grid {
  display:               grid;
  grid-template-columns: repeat(2, 1fr);
  gap:                   var(--space-3);
}

/* The perspective wrapper. A plain <button> otherwise (no
   background/border of its own — .match-tile__face below
   supplies the actual visible surface) EXCEPT it shares that
   face's border-radius, purely so .match-tile--matched's glow
   (a box-shadow on THIS element, not the rotating face inside
   it — see below) is clipped to the same rounded shape instead
   of glowing out past the corners as a square. */
.match-tile {
  height:        96px;
  padding:       0;
  border:        none;
  border-radius: var(--radius-lg);
  background:    none;
  perspective:   800px;
  cursor:        pointer;
}

/* The rotating element. transform-style: preserve-3d keeps
   the two faces in true 3D space — same technique as
   .study-card-flip-inner in study.css, just scoped to a
   single small tile instead of the whole card, and with only
   ONE flip axis (face-down vs face-up) rather than Question/
   Answer sides, since a Match tile only ever shows one piece
   of text, never two. */
.match-tile__inner {
  position:        relative;
  display:         block;
  width:           100%;
  height:          100%;
  transform-style: preserve-3d;
  transform:       rotateY(0deg);
  transition:       transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}

.match-tile--flipped .match-tile__inner,
.match-tile--matched .match-tile__inner {
  transform: rotateY(180deg);
}

.match-tile__face {
  position:            absolute;
  inset:               0;
  display:             flex;
  align-items:         center;
  justify-content:     center;
  padding:             8px;
  border:              2px solid transparent;
  border-radius:       var(--radius-lg);
  backface-visibility: hidden;
  box-shadow:          var(--shadow-elevation-1);
  overflow:            hidden;
}

.match-tile__face--back {
  background-color: var(--tint-accent-soft);
  color:             var(--color-accent-amber);
  transform:         rotateY(0deg);
}

.match-tile__face--front {
  background-color: var(--color-card-bg);
  color:             var(--color-text-primary);
  transform:         rotateY(180deg);
}

/* "Always White Flashcards" — see .quiz-question-card's
   comment above for the full explanation. Only the REVEALED
   face (--front, showing actual question/answer text) is
   pinned white — the face-down --back just shows a decorative
   sparkles icon, not card content, so it's left alone and
   keeps its normal accent-tinted look. Safe to set the literal
   background-color/color directly (not just the token) since
   nothing else overrides this face's own background — the
   only other rule touching .match-tile__face at all
   (.match-tile--matched's green border) doesn't touch either
   property. */
:root[data-white-cards="true"] .match-tile__face--front {
  background-color:     #FFFFFF;
  --color-card-bg:      #FFFFFF;
  --color-text-primary: #000000;
}

/* Scrollable, not just clipped — long card text should still
   be fully readable on a small tile, just via a scroll instead
   of overflowing the grid's fixed row height. */
.match-tile__text {
  width:       100%;
  max-height:  100%;
  overflow-y:  auto;
  text-align:  center;
  font-size:   var(--font-size-footnote);
  line-height: 1.35;
  /* min-height: 0 — CRITICAL. .match-tile__face (its flex
     parent) would otherwise let this flex item grow to fit
     ALL of its text before the "max-height: 100%" above ever
     gets a chance to matter (a flex item's default min-height
     is auto, i.e. "at least as tall as my content"), which
     silently defeats the scroll entirely — long text would
     just push past the tile's fixed height instead of
     scrolling inside it. Same fix study-card-flip-container
     needs for the same reason — see its own comment in
     study.css. */
  min-height:  0;
}

/* Matched pair — permanently revealed, dimmed, and locked
   (pointer-events: none, backed up by the matchFlippedIds/
   matchInputLocked JS guards in handleMatchTileFlip()), with
   a green glow that fades in then back out once right when
   the match lands (see @keyframes match-tile-glow below), plus
   a lasting thin green border on the revealed face afterward
   so a matched tile still reads as "done" once the glow itself
   has faded. color-mix() with the systemGreen token (not a
   hardcoded hex) so this automatically tracks the app's accent
   the same way the card-editor's sparkle glow does. */
.match-tile--matched {
  animation:      match-tile-glow 1400ms ease-out;
  opacity:        0.6;
  pointer-events: none;
  /* Every .match-tile is its OWN stacking context (perspective
     creates one, same as transform does), so without this,
     grid siblings just paint over each other in plain DOM
     order — whichever matched tile happens to sit LATER in
     that order paints on top and silently covers the EARLIER
     one's glow wherever the two overlap (the glow's box-shadow
     spread easily reaches past the 12px grid gap into a
     neighboring tile). Net effect: only one of the two ever
     visibly glows, essentially at random depending on where
     they landed in the shuffle. z-index applies to grid items
     even without an explicit "position" — raising BOTH matched
     tiles above their still-unmatched neighbors is enough to
     let both glows render in full, uncovered by anything else
     in the grid. */
  z-index: 2;
}

.match-tile--matched .match-tile__face {
  border-color: var(--ios-systemGreen);
}

@keyframes match-tile-glow {
  0% {
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--ios-systemGreen) 0%, transparent);
  }
  /* Ramps up to peak brightness, then HOLDS there (25%→60%
     use the identical box-shadow) before fading out — a flat
     plateau in the middle is what actually reads as "longer",
     rather than just stretching a single spike-then-fade
     across more time, which would just look slower, not
     longer-lasting. */
  25%, 60% {
    box-shadow: 0 0 0 4px   color-mix(in srgb, var(--ios-systemGreen) 100%, transparent),
                0 0 26px 8px  color-mix(in srgb, var(--ios-systemGreen) 85%, transparent),
                0 0 42px 16px color-mix(in srgb, var(--ios-systemGreen) 45%, transparent);
  }
  100% {
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--ios-systemGreen) 0%, transparent);
  }
}


/* --- Round Complete (interstitial between rounds) --- */
.match-round-complete {
  display:         flex;
  flex-direction:  column;
  align-items:     center;
  justify-content: center;
  flex:            1;
  gap:             10px;
  padding:         2rem 1.5rem;
  text-align:      center;
}

.match-round-complete__icon {
  display:          flex;
  align-items:      center;
  justify-content:  center;
  width:            64px;
  height:           64px;
  margin-bottom:    6px;
  border-radius:    50%;
  background-color: color-mix(in srgb, var(--ios-systemGreen) 18%, var(--color-card-bg));
  color:             var(--ios-systemGreen);
}

.match-round-complete__title {
  font-size:   var(--font-size-title2);
  font-weight: 700;
  color:       var(--color-text-primary);
}

.match-round-complete__subtitle {
  font-size:   var(--font-size-body);
  color:       var(--color-text-secondary);
  max-width:   280px;
  line-height: 1.5;
}

.match-round-complete__next {
  width:      100%;
  max-width:  320px;
  margin-top: 18px;
}


/* --- Match Complete (whole deck finished) --- */
.match-complete {
  display:         flex;
  flex-direction:  column;
  align-items:     center;
  justify-content: flex-start;
  flex:            1;
  gap:             10px;
  padding:         2rem 1.5rem;
  text-align:      center;
}

.match-complete__emoji {
  font-size:     56px;
  line-height:   1;
  margin-bottom: 6px;
}

.match-complete__title {
  font-size:   var(--font-size-title2);
  font-weight: 700;
  color:       var(--color-text-primary);
}

.match-complete__subtitle {
  font-size:     var(--font-size-body);
  color:         var(--color-text-secondary);
  max-width:     280px;
  line-height:   1.5;
  margin-bottom: 8px;
}

.match-complete__subtitle strong {
  color: var(--color-text-primary);
}

.match-complete__again,
.match-complete__done {
  width:     100%;
  max-width: 320px;
}

.match-complete__again {
  /* Same "push both buttons to the bottom" trick as
     .quiz-complete__again above. */
  margin-top:    auto;
  margin-bottom: 10px;
}

.match-complete__done {
  background-color: var(--ios-tertiarySystemFill);
  color:             var(--color-text-primary);
}

.match-complete__done:hover {
  background-color: var(--ios-secondarySystemFill);
}


/* ═══════════════════════════════════════════════════════
   TYPE THE ANSWER
   Own parallel set of classes for the GAMEPLAY screen, same
   reasoning as Memory Match's .match-* above — see this
   file's top SCOPE note. The deck-select screen is the one
   exception: it's the literal same rendered HTML as Quiz's
   (see renderQuizDeckSelect() in game-modes.js), so no
   .type-deck-* classes exist at all — .quiz-deck-item/
   .quiz-header/etc. above already cover it.
   ═══════════════════════════════════════════════════════ */

#type-play-screen {
  display:        flex;
  flex-direction: column;
  gap:            var(--space-4);
  /* Definite height for the same reason as #quiz-play-screen/
     #match-play-screen above — .type-complete's flex: 1 and
     its "margin-top: auto" button-anchoring trick both need
     real space to grow/push into. */
  height:         100%;
}

/* Same 3-column grid-centered title as .quiz-header/
   .match-header — see .quiz-header's own comment above for
   why grid (not flex) is used. */
.type-header {
  display:               grid;
  grid-template-columns: 1fr auto 1fr;
  align-items:           center;
  gap:                   var(--space-3);
  padding-bottom:        var(--space-3);
  border-bottom:         var(--border-width) solid var(--color-border);
}

/* justify-self: start — see .quiz-header .btn--back's identical
   comment above for why this is needed. */
.type-header .btn--back {
  justify-self: start;
}

.type-header__title {
  grid-column:   2;
  font-size:     var(--font-size-title3);
  font-weight:   700;
  color:         var(--color-text-primary);
  min-width:     0;
  text-align:    center;
  overflow:      hidden;
  text-overflow: ellipsis;
  white-space:   nowrap;
}

/* Running score, top-right of the gameplay header — same
   treatment as .quiz-score. */
.type-score {
  justify-self:     end;
  display:          flex;
  align-items:      center;
  gap:              4px;
  flex-shrink:      0;
  padding:          4px 10px;
  border-radius:    999px;
  background-color: var(--tint-accent-soft);
  color:            var(--color-accent-amber);
  font-size:        var(--font-size-footnote);
  font-weight:      700;
}


/* --- Gameplay: progress row --- */
.type-progress-row {
  display:        flex;
  flex-direction: column;
  gap:            6px;
}

.type-progress-bar-wrap {
  height:           6px;
  border-radius:    999px;
  background-color: var(--ios-tertiarySystemFill);
  overflow:         hidden;
}

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

.type-progress-counter {
  font-size:  var(--font-size-footnote);
  color:      var(--color-text-secondary);
  text-align: center;
}


/* --- Gameplay: question card --- */
.type-question-card {
  display:          flex;
  align-items:      center;
  justify-content:  center;
  min-height:       120px;
  padding:          var(--space-5);
  background-color: var(--color-card-bg);
  border-radius:    var(--radius-lg);
  box-shadow:       var(--shadow-elevation-1);
  text-align:       center;
}

.type-question-card__text {
  font-size:   var(--font-size-title3);
  font-weight: 600;
  color:       var(--color-text-primary);
  line-height: 1.4;
}

/* "Always White Flashcards" Appearance setting — same
   reasoning as .quiz-question-card's identical rule above.
   Safe to set the literal background-color directly here too
   (not just the token) since nothing else ever overrides this
   card's own background. */
:root[data-white-cards="true"] .type-question-card {
  background-color:     #FFFFFF;
  --color-card-bg:      #FFFFFF;
  --color-text-primary: #000000;
}


/* --- Gameplay: answer input --- */
.type-answer-area {
  display: flex;
  gap:     var(--space-3);
}

.type-answer-input {
  flex:             1;
  min-width:        0;
  padding:          var(--space-3) var(--space-4);
  background-color: var(--color-card-bg);
  border:           2px solid var(--color-border);
  border-radius:    var(--border-radius);
  color:            var(--color-text-primary);
  font-size:        var(--font-size-body);
  font-family:      var(--font-primary);
}

.type-answer-input:focus {
  outline:     none;
  border-color: var(--color-accent-amber);
}

.type-answer-input:disabled {
  opacity: 0.7;
}

.type-submit-btn {
  flex-shrink: 0;
}


/* --- Gameplay: feedback (shown after Check Answer) --- */
.type-feedback {
  padding:       var(--space-4);
  border-radius: var(--radius-lg);
  border:        2px solid transparent;
  text-align:    center;
}

.type-feedback__verdict {
  font-size:     var(--font-size-title3);
  font-weight:   700;
  margin-bottom: 6px;
}

.type-feedback__detail {
  font-size:   var(--font-size-footnote);
  color:       var(--color-text-secondary);
  line-height: 1.5;
}

.type-feedback__detail strong {
  color: var(--color-text-primary);
}

/* Correct — green, same semantic color Quiz's own
   .quiz-option--correct already uses for the same meaning. */
.type-feedback--correct {
  background-color: color-mix(in srgb, var(--ios-systemGreen) 14%, var(--color-card-bg));
  border-color:      var(--ios-systemGreen);
}

.type-feedback--correct .type-feedback__verdict {
  color: var(--ios-systemGreen);
}

/* Almost — yellow, the app's existing "in-between" semantic
   color (already used for confidence level 3 of 5 — see
   --color-confidence-3 in theme.css). Deliberately its own
   color rather than a blend of the correct/wrong colors, so
   it reads as its own distinct outcome at a glance, not a
   muddy in-between. */
.type-feedback--almost {
  background-color: color-mix(in srgb, var(--ios-systemYellow) 16%, var(--color-card-bg));
  border-color:      var(--ios-systemYellow);
}

.type-feedback--almost .type-feedback__verdict {
  color: color-mix(in srgb, var(--ios-systemYellow) 70%, black);
  /* Mixed toward black (not used as-is) — systemYellow at full
     saturation is too low-contrast for text on a light
     background; every other verdict color (green/red) reads
     fine as text at full strength, yellow specifically needs
     this adjustment. */
}

/* Wrong — red, same semantic color Quiz's own
   .quiz-option--wrong already uses for the same meaning. */
.type-feedback--wrong {
  background-color: color-mix(in srgb, var(--ios-systemRed) 12%, var(--color-card-bg));
  border-color:      var(--ios-systemRed);
}

.type-feedback--wrong .type-feedback__verdict {
  color: var(--ios-systemRed);
}

.type-next-btn {
  width: 100%;
}


/* --- Type the Answer Complete --- */
.type-complete {
  display:         flex;
  flex-direction:  column;
  align-items:     center;
  justify-content: flex-start;
  flex:            1;
  gap:             10px;
  padding:         2rem 1.5rem;
  text-align:      center;
}

.type-complete__emoji {
  font-size:     56px;
  line-height:   1;
  margin-bottom: 6px;
}

.type-complete__title {
  font-size:   var(--font-size-title2);
  font-weight: 700;
  color:       var(--color-text-primary);
}

.type-complete__subtitle {
  font-size:     var(--font-size-body);
  color:         var(--color-text-secondary);
  max-width:     280px;
  line-height:   1.5;
  margin-bottom: 4px;
}

.type-complete__subtitle strong {
  color: var(--color-text-primary);
}

/* The 3-way Correct/Almost/Wrong breakdown — Quiz and Match
   only ever have ONE outcome to show (a plain X/Y score), so
   neither needed anything like this. */
.type-complete__stats {
  display: flex;
  gap:     var(--space-3);
  margin-bottom: 8px;
}

.type-complete__stat {
  padding:       6px 14px;
  border-radius: 999px;
  font-size:     var(--font-size-footnote);
  font-weight:   600;
}

.type-complete__stat strong {
  font-size: var(--font-size-body);
}

.type-complete__stat--correct {
  background-color: color-mix(in srgb, var(--ios-systemGreen) 16%, transparent);
  color:             var(--ios-systemGreen);
}

.type-complete__stat--almost {
  background-color: color-mix(in srgb, var(--ios-systemYellow) 20%, transparent);
  color:             color-mix(in srgb, var(--ios-systemYellow) 70%, black);
}

.type-complete__stat--wrong {
  background-color: color-mix(in srgb, var(--ios-systemRed) 14%, transparent);
  color:             var(--ios-systemRed);
}

.type-complete__again,
.type-complete__done {
  width:     100%;
  max-width: 320px;
}

.type-complete__again {
  /* Same "push both buttons to the bottom" trick as
     .quiz-complete__again/.match-complete__again above. */
  margin-top:    auto;
  margin-bottom: 10px;
}

.type-complete__done {
  background-color: var(--ios-tertiarySystemFill);
  color:             var(--color-text-primary);
}

.type-complete__done:hover {
  background-color: var(--ios-secondarySystemFill);
}
