/* ——— Blunder Override ———
   Theme-aware stylesheet: uses all tokens from style_design_sigma.css
   and style_dark.css so it renders cleanly in both light + dark themes. */

/* The `hidden` attribute is only `display:none` at user-agent specificity, so
   ANY author `display` rule silently defeats it. Both `.mistakes-workspace`
   and `.mistakes-promo` set `display:flex`, which made the empty board and the
   Session Progress / Override Queue cards render on a fresh page load despite
   being marked hidden. One scoped rule makes the attribute authoritative. */
body.mistakes-page [hidden] {
  display: none !important;
}

/* Remove the 12px board border (the "gray outer shell") on the blunder
   override page, matching the review page and training pages. The stage's
   aspect-ratio already squares the board against its cell — the border
   was a second constraint. */
body.mistakes-page .review-board {
  border: none;
}

/* The eval bar is capped at 50% of the wrap height and centred, so its
   bottom edge sits at 75% of the wrap. Position the label right below it,
   matching the review page's treatment. */
body.mistakes-page .review-eval-label {
  top: 75%;
  bottom: auto;
}

/* ==== Layout root ====================================================== */

.mistakes-root {
  display: flex;
  flex-direction: column;
  /* No gap. The children are the status line, the menu and one panel, and each
     already carries its own margin — the 18px between them was padding stacked
     on padding, and on the trainer it came straight off the board. The top
     padding is what sets the first child off the header now. */
  gap: 0;
  padding: 8px 0 48px;
  max-width: 1360px;
  width: 100%;
  min-width: 0;
  box-sizing: border-box;
  animation: om-fade-in 0.35s ease-out both;
}

/* The theme switch is not rendered on this page.

   It is the one piece of always-on chrome left above the content, and on a page
   whose whole purpose is a board that should fill the space it is given, it is
   the least useful thing there: two buttons restating a preference the reader
   has already made, in a header that is otherwise empty.

   Removed in base.html, scoped to this page's endpoint — not hidden here — so
   it also leaves the tab order and the accessibility tree. */

@keyframes om-fade-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ==== Status line ======================================================
   (The hero header now reuses .review-intro / .review-kicker / .sr-only /
   .review-quota so this page matches Game Review, so the old
   .mistakes-intro* / .mistakes-lead rules are gone.) */

.mistakes-status {
  /* Mirror .review-status: a plain reserved line rather than a padded box, so
     the picker below starts at the same height on both pages. */
  min-height: 1.25rem;
  margin: 0;
  color: var(--muted);
  font-size: 0.92rem;
  transition: color 0.2s ease;
}

.mistakes-status:empty {
  padding: 0;
  border: 0;
  background: transparent;
}

.mistakes-status.is-error {
  color: var(--danger-text);
}

/* ==== Import panel (picker) ============================================
   The picker markup now reuses the Game Review classes (review-picker,
   review-tabs, review-tab, review-panel, review-label, review-select,
   review-input, review-pgn, review-quota) so both pages look identical.
   style_review.css is already loaded by mistakes.html.
   Only the scan grid and the PGN action row remain page-specific. */

/* ---- Scan grid ---- */
.mistakes-scan-grid {
  display: grid;
  grid-template-columns: 140px 1fr 200px auto;
  gap: 16px;
  align-items: end;
}

@media (max-width: 768px) {
  .mistakes-scan-grid { grid-template-columns: 1fr; }
}

.mistakes-field {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.mistakes-pgn-actions {
  display: flex;
  gap: 10px;
  margin-top: 16px;
  flex-wrap: wrap;
}

.mistakes-scan-progress {
  margin-top: 26px;
  padding-top: 20px;
  border-top: 1px solid var(--line);
}

.mistakes-scan-progress-header {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 0.88rem;
  font-weight: 700;
  color: var(--cream);
  margin-bottom: 10px;
}

.mistakes-scan-progress-header #scan-progress-pct {
  margin-left: auto;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
}

.mistakes-scan-cancel {
  padding: 5px 12px;
  font-size: 0.78rem;
  border-radius: 8px;
}

.mistakes-progress-track {
  height: 10px;
  border-radius: 999px;
  background: var(--fill-subtle);
  border: 1px solid var(--line);
  overflow: hidden;
  margin-bottom: 12px;
}

.mistakes-progress-bar {
  height: 100%;
  width: 0%;
  border-radius: 999px;
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--gold) 80%, var(--gold-deep)),
    var(--gold-bright));
  transition: width 0.25s cubic-bezier(.2,.7,.3,1);
  box-shadow: 0 0 12px color-mix(in srgb, var(--gold) 45%, transparent);
}

/* ==== The menu: everything found, ready to train =======================

   The page used to offer one way in: a row per game in the picker, each of
   which re-scanned that game with Stockfish. Assembling a session cost a scan
   per game, and the page could not say what was there until you had paid for one.

   This is the way in instead. It reads the summaries Game Review already stored,
   so opening it costs nothing, and it is grouped by game only so a position is
   identifiable — the primary action trains all of them at once. */

.mistakes-menu {
  margin-bottom: 22px;
  padding: 20px 22px;
  border: 1px solid var(--line-strong);
  border-radius: 18px;
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--gold) 6%, transparent), transparent 220px),
    color-mix(in srgb, var(--bg-2) 55%, transparent);
}

.mistakes-menu[hidden] {
  display: none !important;
}

.mistakes-menu-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 18px 24px;
  flex-wrap: wrap;
}

.mistakes-menu-headline {
  min-width: 0;
}

.mistakes-menu-title {
  margin: 2px 0 0;
  font-size: 1.5rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--cream);
}

.mistakes-menu-lead {
  margin: 6px 0 0;
  max-width: 56ch;
  font-size: 0.92rem;
  line-height: 1.55;
  color: var(--muted);
}

/* The tallies are the answer to "is there anything here", so they are the most
   prominent thing after the title. Tabular figures so the numbers do not jitter
   as they change after a scan. */
.mistakes-menu-tallies {
  display: flex;
  gap: 10px;
  flex: 0 0 auto;
}

.mistakes-menu-tallies[hidden] {
  display: none !important;
}

.mistakes-menu-tally {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  min-width: 74px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: color-mix(in srgb, var(--bg-3) 60%, transparent);
}

.mistakes-menu-tally-num {
  font-size: 1.5rem;
  font-weight: 800;
  line-height: 1.1;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
}

.mistakes-menu-tally-label {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}

.mistakes-menu-actions {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin: 18px 0 4px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--line);
}

.mistakes-menu-start {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 11px 20px;
  font-size: 1rem;
  font-weight: 700;
}

.mistakes-menu-start:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.mistakes-menu-note {
  margin: 0;
  font-size: 0.84rem;
  line-height: 1.5;
  color: var(--muted);
}

.mistakes-menu-groups {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 16px;
}

.mistakes-menu-groups:empty {
  display: none;
}

/* A group header is a button: clicking it trains that one game, which is the
   per-game entry point without making anyone choose before the default. */
.mistakes-menu-group-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: color-mix(in srgb, var(--bg-3) 55%, transparent);
  color: var(--cream);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.18s ease, background 0.18s ease;
}

.mistakes-menu-group-head:hover {
  border-color: var(--gold);
  background: color-mix(in srgb, var(--gold) 8%, transparent);
}

.mistakes-menu-group-title {
  font-size: 0.94rem;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.mistakes-menu-group-meta {
  flex: 0 0 auto;
  font-size: 0.78rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.mistakes-menu-items {
  list-style: none;
  margin: 6px 0 0;
  padding: 0 0 2px 4px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.mistakes-menu-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 6px 12px 6px 14px;
  border-left: 2px solid var(--line);
  font-size: 0.86rem;
}

.mistakes-menu-item-move {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex: 0 0 auto;
  min-width: 96px;
}

.mistakes-menu-item-ply {
  color: var(--muted);
  font-size: 0.76rem;
  font-variant-numeric: tabular-nums;
  min-width: 34px;
}

.mistakes-menu-item-move code {
  font-family: var(--font-mono, ui-monospace, monospace);
  font-weight: 700;
  color: var(--cream);
}

/* The reason, not the colour, carries the meaning: a dropped piece and a thrown
   win are different lessons and are trained differently. */
.mistakes-menu-item-why {
  flex: 1 1 auto;
  min-width: 0;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.mistakes-menu-item-why.is-clear {
  color: var(--danger-text);
}

.mistakes-menu-item-why.is-thrown {
  color: var(--gold);
}

/* An already-lost position. Muted rather than alarming: the move was still a
   mistake, but there was no advantage to hand back, and colouring it like a
   dropped piece would overstate what happened. */
.mistakes-menu-item-why.is-drifting {
  color: var(--muted);
  opacity: 0.8;
}

.mistakes-menu-item-loss {
  flex: 0 0 auto;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.mistakes-menu-item-loss::after {
  content: " cp";
  opacity: 0.7;
}

@media (max-width: 640px) {
  .mistakes-menu { padding: 16px; }
  .mistakes-menu-title { font-size: 1.28rem; }
  .mistakes-menu-tally { min-width: 60px; padding: 8px 9px; }
  .mistakes-menu-tally-num { font-size: 1.2rem; }
  .mistakes-menu-tallies { gap: 7px; }
  .mistakes-menu-item { gap: 8px; padding-left: 10px; }
  .mistakes-menu-item-move { min-width: 0; }
}

.mistakes-scan-stats {
  display: flex;
  gap: 22px;
  font-size: 0.82rem;
  color: var(--muted);
  flex-wrap: wrap;
}

.mistakes-scan-stats strong {
  color: var(--cream);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* ==== Workspace layout ================================================= */

.mistakes-workspace {
  display: flex;
  flex-direction: column;
  /* No gap. The only child is the layout, and the page's top padding already
     sets it off from the header — a 20px gap here was pure margin on top of
     that, and it came straight off the board. The top bar that used to be the
     first child (and the reason this needed a gap) is gone. */
  gap: 0;
  animation: om-fade-in 0.3s ease-out both;
}

.mistakes-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 360px;
  gap: 28px;
  align-items: start;
}

@media (max-width: 900px) {
  .mistakes-layout { grid-template-columns: 1fr; }
}

.mistakes-board-col {
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-width: 0;
}

.mistakes-board-shell {
  max-width: 640px;
  width: 100%;
}

/* ==== Context card (blunder banner + game meta) ======================== */

.mistakes-context-card {
  border: 1px solid var(--line-strong);
  border-radius: 18px;
  background: var(--panel);
  padding: 18px 20px;
  box-shadow: var(--panel-glow);
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.mistakes-context-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.mistakes-source-badge {
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--fill-subtle);
  border: 1px solid var(--line);
  font-size: 0.7rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}

.mistakes-game-title {
  font-weight: 700;
  font-size: 0.94rem;
  color: var(--cream);
}

/* --- Blunder banner (contextual) --- */

.mistakes-blunder-banner {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  padding: 14px 16px;
  background: var(--danger-bg);
  border: 1px solid var(--danger-border);
  border-radius: 14px;
}

.mistakes-blunder-icon {
  font-size: 1.4rem;
  line-height: 1;
  padding-top: 2px;
  flex-shrink: 0;
}

.mistakes-blunder-text {
  font-size: 0.92rem;
  color: var(--cream);
  line-height: 1.55;
  flex: 1;
  min-width: 0;
}

.mistakes-blunder-text code {
  background: color-mix(in srgb, var(--danger-text) 12%, transparent);
  padding: 2px 7px;
  border-radius: 6px;
  color: var(--danger-text);
  font-weight: 800;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.82em;
  border: 1px solid color-mix(in srgb, var(--danger-text) 24%, transparent);
}

.mistakes-goal-text {
  margin-top: 6px;
  font-weight: 800;
  color: var(--gold);
  letter-spacing: 0.01em;
}

/* ==== Board controls ====

   One bar, not a row of loose buttons.

   The row used to be five independent `.btn` elements at `gap: 10px`: a hint, a
   replay, a solution, a retry and a gold Next at the end. Ten pixels between
   bare buttons reads as unrelated controls, and it wrapped — two rows on a
   narrow window — which pushed the bottom of the column past the fold.

   It now shares the Game Review transport's own class (`.review-board-controls`)
   and that bar's own button classes, so the two boards are the same instrument:
   a filled surface with an inner hairline, a filled primary on the left, quiet
   square controls in the middle, and a live readout on the right.

   Only the two page-specific rules live here. Everything else — the surface, the
   button, the primary, the divider, the readout — is inherited from
   style_review.css, which this page already loads, so there is exactly one
   definition of what a board transport looks like.

   `flex-wrap: nowrap` is inherited from the shared bar, and that is deliberate
   rather than incidental: a wrapped control row is what pushes a control off
   the bottom of a page that does not scroll. */

.mistakes-controls {
  /* Inherits the bar from .review-board-controls. Sized up to match the review
     page's desktop transport, which is the larger of the two.

     `grid-column: 2` from the shared bar is inert here — this column is a flex
     stack, not a grid — so it is cancelled rather than left to depend on that
     staying true. If the bar is ever placed in a grid, the reset is what stops
     it being pushed out of a track it does not belong to. */
  grid-column: auto;
  gap: 6px;
  padding: 7px;
  border-radius: 15px;
}

.mistakes-controls .review-ctl-primary {
  height: 44px;
  padding: 0 20px;
  border-radius: 11px;
  font-size: 1rem;
}

/* Control icons: inline SVGs sized and aligned as a unit next to their label.
   They inherit currentColor, so a button keeps one colour in every theme. */
.mistakes-btn-icon {
  width: 17px;
  height: 17px;
  flex: 0 0 auto;
  display: block;
  opacity: 0.85;
}

.mistakes-controls .review-ctl-label {
  white-space: nowrap;
}

.mistakes-controls .review-ctl:hover .mistakes-btn-icon,
.mistakes-controls .review-ctl:focus-visible .mistakes-btn-icon {
  opacity: 1;
}

/* ==== Side column: cards, stats, queue ================================= */

.mistakes-side {
  display: flex;
  flex-direction: column;
  gap: 20px;
  position: sticky;
  top: 16px;
}

@media (max-width: 900px) {
  .mistakes-side { position: static; }
}

.mistakes-side-card {
  border: 1px solid var(--line-strong);
  border-radius: 18px;
  background: var(--panel);
  padding: 20px;
  box-shadow: var(--panel-glow);
}

.mistakes-side-title {
  margin: 0 0 14px;
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ---- Stats grid ---- */

.mistakes-stat-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}

.mistakes-stat-pill {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 14px 6px;
  background: var(--fill-subtle);
  border: 1px solid var(--line);
  border-radius: 14px;
  transition: transform 0.18s ease, border-color 0.18s ease;
}

.mistakes-stat-pill:hover {
  transform: translateY(-1px);
  border-color: color-mix(in srgb, var(--gold) 55%, var(--line));
}

.mistakes-stat-num {
  font-size: 1.5rem;
  font-weight: 800;
  color: var(--cream);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

.mistakes-stat-label {
  font-size: 0.65rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
  margin-top: 6px;
}

/* ---- Queue header ---- */

.mistakes-queue-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 14px;
  gap: 12px;
}

.mistakes-queue-header .mistakes-side-title { margin: 0; }

/* ---- Queue list ---- */

.mistakes-queue-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 520px;
  overflow-y: auto;
  padding-right: 4px;
}

.mistakes-queue-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px;
  border-radius: 14px;
  background: var(--fill-subtle);
  border: 1px solid var(--line);
  cursor: pointer;
  transition: all 0.18s cubic-bezier(.2,.7,.3,1);
  text-align: left;
  color: var(--cream);
  font-family: var(--font);
  position: relative;
  overflow: hidden;
}

.mistakes-queue-item:hover {
  border-color: var(--line-strong);
  background: var(--hover-fill);
  transform: translateX(2px);
}

.mistakes-queue-item:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 1px;
}

.mistakes-queue-item.is-active {
  border-color: color-mix(in srgb, var(--gold) 70%, var(--line-strong));
  background: color-mix(in srgb, var(--gold) 14%, var(--fill-subtle));
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--gold) 25%, transparent),
    0 6px 22px color-mix(in srgb, var(--gold) 14%, transparent);
}

.mistakes-queue-item.is-solved {
  border-color: color-mix(in srgb, #22c55e 45%, var(--line));
  background: color-mix(in srgb, #22c55e 8%, var(--fill-subtle));
}

.mistakes-queue-item.is-solved.is-active {
  border-color: color-mix(in srgb, #22c55e 65%, var(--line-strong));
}

.mistakes-item-left {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  flex: 1;
}

.mistakes-item-idx {
  font-weight: 800;
  font-size: 0.78rem;
  color: var(--muted);
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: var(--panel);
  border: 1px solid var(--line);
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}

.mistakes-queue-item.is-solved .mistakes-item-idx {
  background: color-mix(in srgb, #22c55e 18%, var(--panel));
  color: color-mix(in srgb, #22c55e 85%, var(--cream));
  border-color: color-mix(in srgb, #22c55e 50%, var(--line));
}

.mistakes-item-info {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.mistakes-item-title {
  font-weight: 700;
  font-size: 0.86rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.mistakes-item-subtitle {
  font-size: 0.72rem;
  color: var(--muted);
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Which kind of mistake this is. A dropped piece is the unambiguous case and
   is called out; a collapsed advantage is the softer one. */
.mistakes-item-tier {
  display: inline-block;
  margin-top: 3px;
  padding: 1px 6px;
  border: 1px solid color-mix(in srgb, var(--data-warn) 34%, var(--line));
  border-radius: 999px;
  background: color-mix(in srgb, var(--data-warn) 10%, transparent);
  color: var(--data-warn);
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  white-space: nowrap;
}

.mistakes-item-tier.is-clear {
  border-color: color-mix(in srgb, var(--data-loss) 42%, var(--line));
  background: color-mix(in srgb, var(--data-loss) 12%, transparent);
  color: var(--data-loss);
}

/* A thrown lead, and a position that was already lost. They are deliberately
   different treatments: a thrown win was the reader's to lose, so it is
   highlighted; an already-lost position is quieter, because it is the least
   useful thing to open a session with and should not read as urgent. */
.mistakes-item-tier.is-thrown {
  border-color: color-mix(in srgb, var(--gold) 42%, var(--line));
  background: color-mix(in srgb, var(--gold) 12%, transparent);
  color: var(--gold);
}

.mistakes-item-tier.is-drifting {
  border-color: var(--line);
  background: color-mix(in srgb, var(--bg-3) 55%, transparent);
  color: var(--muted);
}

.mistakes-item-badge {
  font-size: 0.82rem;
  padding-left: 8px;
  flex-shrink: 0;
}

/* ==== Board square states ==== */

.square.selected-piece {
  box-shadow: inset 0 0 0 3px var(--gold) !important;
  background: color-mix(in srgb, var(--gold) 24%, var(--felt)) !important;
}

.square.legal-dest {
  position: relative;
}

.square.legal-dest::after {
  content: "";
  position: absolute;
  width: 28%;
  height: 28%;
  border-radius: 50%;
  background: color-mix(in srgb, #22c55e 70%, transparent);
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
  box-shadow: 0 0 8px color-mix(in srgb, #22c55e 50%, transparent);
}

.square.hint-piece {
  animation: hint-pulse 1.1s infinite alternate;
}

@keyframes hint-pulse {
  from { box-shadow: inset 0 0 0 3px color-mix(in srgb, var(--gold) 85%, transparent); }
  to   { box-shadow: inset 0 0 0 7px color-mix(in srgb, var(--gold) 30%, transparent); }
}

.square.blunder-piece {
  box-shadow: inset 0 0 0 3px var(--danger-text) !important;
  background: color-mix(in srgb, var(--danger-text) 20%, var(--felt)) !important;
}

.square.correct-piece {
  box-shadow: inset 0 0 0 3px color-mix(in srgb, #22c55e 90%, transparent) !important;
  background: color-mix(in srgb, #22c55e 18%, var(--felt)) !important;
}

.shake-board {
  animation: shake 0.35s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
}

@keyframes shake {
  10%, 90% { transform: translate3d(-2px, 0, 0); }
  20%, 80% { transform: translate3d(3px, 0, 0); }
  30%, 50%, 70% { transform: translate3d(-4px, 0, 0); }
  40%, 60% { transform: translate3d(4px, 0, 0); }
}

/* ==== Promotion picker overlay ==== */

.mistakes-root .review-board-shell { position: relative; }

.mistakes-promo {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  background: color-mix(in srgb, var(--overlay-bg) 82%, transparent);
  backdrop-filter: blur(4px);
  /* Square, to match the board it covers — same reason as the review page's
     picker: this is inset to the stage, so a radius would round the corners of
     an edge that is now square underneath it. */
  border-radius: 0;
  z-index: 30;
  animation: om-fade-in 0.18s ease-out both;
}

.mistakes-promo[hidden] { display: none !important; }

.mistakes-promo-title {
  margin: 0;
  font-size: 0.76rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--cream);
}

.mistakes-promo-options {
  display: flex;
  gap: 12px;
}

.mistakes-promo-btn {
  width: 64px;
  height: 64px;
  padding: 6px;
  border-radius: 14px;
  border: 1px solid var(--line-strong);
  background: var(--panel);
  cursor: pointer;
  transition: all 0.18s ease;
  box-shadow: var(--panel-glow);
}

.mistakes-promo-btn img {
  width: 100%;
  height: 100%;
  display: block;
}

.mistakes-promo-btn:hover {
  border-color: var(--gold);
  transform: translateY(-3px) scale(1.04);
  box-shadow:
    var(--panel-glow-hover),
    0 0 0 1px color-mix(in srgb, var(--gold) 30%, transparent);
}

/* ==== Narrow screens & responsive padding ============================= */

@media (max-width: 640px) {
  .mistakes-context-card { padding: 14px 16px; }
  .mistakes-side-card { padding: 16px; }
  .mistakes-scan-stats { gap: 14px; }
  .mistakes-lead { font-size: 0.94rem; }
}

/* ==== Reduced motion ================================================== */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
