/* ==========================================================
   Achievement Unlocked / Hidden Easter Egg / Bug Squash.
   Everything in this file is prefixed "mkp-" so it can never
   collide with or override anything in style.css — with one
   deliberate, documented exception: the ".site-footer" rule
   below, which only touches display/grid-template-columns to
   center the achievement cluster (see that rule for why).
   ========================================================== */

/* ---------- Achievement Unlocked (toast, bottom-right) ---------- */
.mkp-ach-toast {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 9999;
  display: flex;
  gap: 12px;
  align-items: center;
  max-width: min(320px, calc(100vw - 40px));
  background: var(--panel-2);
  border: 1px solid var(--panel-border-strong);
  border-radius: 14px;
  padding: 14px 18px;
  box-shadow: var(--shadow-lg);
  /* Starts slightly smaller and lower — roughly how a depth-1 stack
     card looks (see ".mkp-ach-stack-item" below) — rather than just
     lower, so an incoming toast that WAS sitting in the stack reads as
     growing into place instead of popping in from nowhere. */
  transform: translateY(14px) scale(0.94);
  opacity: 0;
  transition: transform 0.4s cubic-bezier(.2,.8,.2,1), opacity 0.4s ease;
  pointer-events: none;
}
.mkp-ach-toast.mkp-show { transform: translateY(0) scale(1); opacity: 1; }
/* Preferred spot on wide viewports: the right margin, vertically
   centered on the page — a mirror of .scroll-rail sitting in the left
   margin (see style.css), so the two read as a matched, symmetric pair
   instead of the toast floating independently in a corner. Applied via
   JS (see useDockedToastLayout()/applyToastPosition() in features.js)
   at the same 1500px breakpoint the rail itself uses. Deliberately
   narrower + denser than the corner version (no description line) so
   its footprint stays comfortable in that margin. Falls back to the
   roomier bottom-right layout below on narrower viewports, where the
   rail itself is hidden too. */
.mkp-ach-toast.mkp-rail-pos {
  right: auto;
  bottom: auto;
  width: 176px;
  max-width: 176px;
  gap: 8px;
  padding: 10px 12px;
}
@media (min-width: 1500px) {
  .mkp-ach-toast.mkp-rail-pos {
    /* NOT a plain mirror of .scroll-rail's own "- 132px" offset: the
       rail is only 70px wide, so that offset alone already leaves it a
       clear 62px gap from the content column. This toast is 176px wide
       — mirroring the same "-132px" put its NEAR edge 44px INTO the
       content column instead (132 - 176 = -44), which is exactly what
       read as "too close, blends in with References/etc." Solving for
       that same ~62px gap given this toast's own width: gap(62) +
       width(176) = 238px. The max(16px, …) floor keeps it from being
       pushed off-screen at the low end of this breakpoint (at exactly
       1500px the side margin is only 160px, less than 238px). */
    right: max(16px, calc((100vw - var(--max-w, 1180px)) / 2 - 238px));
    top: 50%;
    bottom: auto;
    transform: translateY(calc(-50% + 14px)) scale(0.94);
  }
  .mkp-ach-toast.mkp-rail-pos.mkp-show { transform: translateY(-50%) scale(1); }
}
.mkp-ach-toast.mkp-rail-pos .mkp-ach-badge { width: 30px; height: 30px; font-size: 15px; border-radius: 8px; }
.mkp-ach-toast.mkp-rail-pos .mkp-ach-eyebrow { font-size: 9px; }
.mkp-ach-toast.mkp-rail-pos .mkp-ach-title { font-size: 12.5px; line-height: 1.25; }
.mkp-ach-toast.mkp-rail-pos .mkp-ach-desc { font-size: 10.5px; margin-top: 1px; }
.mkp-ach-badge {
  flex-shrink: 0;
  width: 42px;
  height: 42px;
  border-radius: 10px;
  background: conic-gradient(from 140deg, var(--brass-bright), var(--brass-dim), var(--brass-bright));
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
}
.mkp-ach-eyebrow {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--brass-bright);
}
.mkp-ach-title { font-family: var(--font-display); font-weight: 600; font-size: 14.5px; margin-top: 2px; color: var(--ink); }
.mkp-ach-desc { font-family: var(--font-mono); font-size: 11.5px; color: var(--ink-muted); margin-top: 2px; }

@media (max-width: 640px) {
  .mkp-ach-toast { right: 14px; bottom: 14px; left: 14px; max-width: none; }
}

/* ---------- Glow — every achievement toast gets this while it's the
   one actively on screen, not the stacked cards waiting behind it (see
   ".mkp-ach-stack-item" below, which is explicitly excluded). Used to
   be KUDOS-only; generalized so every unlock reads as equally
   celebratory rather than just the 10/10 finale. ---------- */
.mkp-ach-toast.mkp-show:not(.mkp-ach-stack-item) {
  animation: mkpAchGlow 1.6s ease-in-out infinite;
}
@keyframes mkpAchGlow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(232, 195, 126, 0), var(--shadow-lg); }
  50% { box-shadow: 0 0 22px 4px rgba(232, 195, 126, 0.45), var(--shadow-lg); }
}

/* ---------- Full completion (10/10) — a bigger version of the ordinary
   toast (the glow above now applies to it same as every other unlock),
   queued through the same pipeline so it always lands in the same
   guaranteed-visible spot as every other achievement, plus the confetti
   + chime that go with it. ---------- */
.mkp-ach-toast.mkp-celebration-toast {
  border-color: var(--brass);
}
.mkp-celebration-badge { font-size: 22px; }
.mkp-celebration-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 14.5px;
  letter-spacing: 0.03em;
  color: var(--brass-bright);
  text-shadow: 0 0 10px rgba(232, 195, 126, 0.5);
}
.mkp-celebration-sub { font-family: var(--font-mono); font-size: 11.5px; color: var(--ink); margin-top: 3px; }
/* Rail-docked variant needs its own (later, so it wins) size step down,
   same reasoning as the plain achievement toast's compact layout. */
.mkp-ach-toast.mkp-rail-pos .mkp-celebration-badge { font-size: 17px; }
.mkp-ach-toast.mkp-rail-pos .mkp-celebration-title { font-size: 11.5px; letter-spacing: 0.02em; }
.mkp-ach-toast.mkp-rail-pos .mkp-celebration-sub { font-size: 10px; margin-top: 2px; }

.mkp-confetti-piece {
  position: fixed;
  z-index: 10002;
  border-radius: 2px;
  pointer-events: none;
  animation: mkpConfettiFly 1.3s cubic-bezier(.15, .7, .3, 1) forwards;
}
@keyframes mkpConfettiFly {
  0% { transform: translate(0, 0) rotate(0deg); opacity: 1; }
  65% { opacity: 1; }
  100% { transform: translate(var(--dx), var(--dy)) rotate(var(--rot)); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .mkp-confetti-piece { display: none; }
  .mkp-ach-toast.mkp-show { animation: none; }
}

/* ---------- Stacked achievements — when more than one unlocks while a
   toast is already on screen, the queued ones render (see renderStack()
   in features.js) as a shallow stack of icon-only cards peeking out
   behind the active toast, in the same corner/docked spot, instead of
   just waiting invisibly. Timing is unchanged — still one full toast at
   a time, same durations as before — this is purely the "more coming"
   visual. Depth (1 = right behind the active toast) comes in as the
   --mkp-stack-depth custom property set per card in JS. ---------- */
.mkp-ach-toast.mkp-ach-stack-item {
  padding: 10px 14px;
  gap: 0;
  pointer-events: none;
  animation: none;
  transition: transform 0.35s cubic-bezier(.2,.8,.2,1), opacity 0.35s ease;
}
.mkp-ach-toast.mkp-ach-stack-item .mkp-ach-badge {
  width: 34px;
  height: 34px;
  font-size: 16px;
}
.mkp-ach-toast.mkp-ach-stack-item.mkp-show {
  transform: translateY(calc(var(--mkp-stack-depth) * 16px)) scale(calc(1 - var(--mkp-stack-depth) * 0.07));
  opacity: calc(1 - var(--mkp-stack-depth) * 0.24);
  z-index: calc(9999 - var(--mkp-stack-depth));
}
@media (min-width: 1500px) {
  .mkp-ach-toast.mkp-rail-pos.mkp-ach-stack-item.mkp-show {
    transform: translateY(calc(-50% + var(--mkp-stack-depth) * 16px)) scale(calc(1 - var(--mkp-stack-depth) * 0.07));
  }
}
@media (prefers-reduced-motion: reduce) {
  .mkp-ach-toast.mkp-ach-stack-item.mkp-show { transition: none; }
}

/* ---------- Hidden Easter Egg (Konami code -> overlay) ---------- */
.mkp-egg-backdrop {
  position: fixed;
  inset: 0;
  z-index: 10000;
  background: rgba(8, 4, 14, 0.78);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
}
.mkp-egg-backdrop.mkp-open { opacity: 1; pointer-events: auto; }
.mkp-egg-card {
  width: 100%;
  max-width: 420px;
  background: var(--bg);
  border: 1px solid var(--panel-border-strong);
  border-radius: var(--radius-lg);
  padding: 28px 26px;
  box-shadow: var(--shadow-lg);
  transform: translateY(14px) scale(0.98);
  transition: transform 0.35s cubic-bezier(.2,.8,.2,1);
}
.mkp-egg-backdrop.mkp-open .mkp-egg-card { transform: translateY(0) scale(1); }
.mkp-egg-kicker {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #1a1006;
  background: linear-gradient(135deg, var(--brass-bright), var(--brass));
  display: inline-block;
  padding: 4px 10px;
  border-radius: 5px;
  font-weight: 600;
  margin-bottom: 16px;
}
.mkp-egg-line {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--success);
  margin: 0 0 9px;
}
.mkp-egg-line.mkp-dim { color: var(--ink-faint); }
.mkp-egg-close {
  margin-top: 14px;
}

/* ---------- Footer layout — one deliberate, documented exception to
   this file's "never override style.css" rule above: .site-footer's
   own flex/space-between (style.css) leaves its middle child sitting
   wherever its own width happens to land, not truly centered on the
   bar. Overriding just `display`+`grid-template-columns` here (nothing
   else) turns it into a real 3-column layout so the achievement
   cluster sits centered — matching the scroll-rail's placement in the
   opposite (left) margin — while the copyright line and hidden bug
   keep their same spots at the outer edges. ---------- */
.site-footer {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
}
.site-footer > *:first-child { justify-self: start; }
.site-footer > *:last-child { justify-self: end; }
@media (max-width: 640px) {
  .site-footer { grid-template-columns: 1fr; justify-items: center; text-align: center; }
}

/* ---------- Achievement counter — an icon-chip cluster + progress bar,
   sitting between the copyright line and the hidden bug. Always
   visible (unlike the bug itself), so it hints there's more here than
   the copyright line without pointing straight at where.
   - Locked chips: no background, no border, opacity down near nothing
     (0.14) plus grayscale — barely a suggestion they're there.
   - Found-but-incomplete chips: a faint neutral wash and a partly
     desaturated glyph — clearly "on" without giving away real color
     or a glow, and deliberately NOT gold, so gold stays a 10/10-only
     payoff. No per-chip tooltip, on purpose — hovering never reveals
     which achievement a given icon actually is.
   - Complete (10/10): chips, bar and text all turn gold + full color
     at once. ---------- */
.mkp-ach-cluster {
  display: inline-grid;
  grid-auto-flow: row;
  row-gap: 10px;
  justify-items: stretch;
}
.mkp-ach-chip-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
}
.mkp-ach-chip {
  width: 24px;
  height: 24px;
  border-radius: 7px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  background: none;
  border: none;
  opacity: 0.14;
  filter: grayscale(1);
  transition: opacity 0.3s ease, filter 0.3s ease, background 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;
}
.mkp-ach-chip.mkp-found {
  opacity: 0.55;
  filter: grayscale(0.6) brightness(0.95);
  background: rgba(182, 169, 201, 0.07);
  border: 1px solid rgba(182, 169, 201, 0.22);
}
.mkp-ach-cluster.mkp-complete .mkp-ach-chip.mkp-found {
  opacity: 1;
  filter: none;
  background: conic-gradient(from 140deg, var(--brass-bright), var(--brass-dim), var(--brass-bright));
  border-color: var(--brass);
  box-shadow: 0 0 8px 1px rgba(232, 195, 126, 0.4);
}
.mkp-ach-count {
  font-family: var(--font-mono);
  font-size: 11px;
  white-space: nowrap;
  color: var(--ink-faint);
  margin-left: 4px;
  padding-left: 10px;
  border-left: 1px solid var(--panel-border);
  transition: color 0.3s ease, text-shadow 0.3s ease, border-color 0.3s ease;
}
.mkp-ach-bar-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
}
.mkp-ach-bar {
  flex: 1 1 auto;
  min-width: 0;
  height: 7px;
  background: var(--panel-2);
  border: 1px solid var(--panel-border);
  border-radius: 100px;
  overflow: hidden;
}
.mkp-ach-bar-fill {
  display: block;
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, rgba(182, 169, 201, 0.35), rgba(182, 169, 201, 0.65));
  border-radius: 100px;
  transition: width 0.5s ease, background 0.3s ease, box-shadow 0.3s ease;
}
.mkp-ach-cluster.mkp-complete .mkp-ach-bar-fill {
  background: linear-gradient(90deg, var(--brass-dim), var(--brass-bright));
  box-shadow: 0 0 10px 1px rgba(232, 195, 126, 0.5);
}
.mkp-ach-xp {
  font-family: var(--font-mono);
  font-size: 11px;
  white-space: nowrap;
  color: var(--ink-faint);
  transition: color 0.3s ease, text-shadow 0.3s ease;
}
/* All 10 achievements found — the count + XP text turn gold so the
   "done" state is still visible later, even long after the KUDOS toast
   and its confetti have faded. */
.mkp-ach-cluster.mkp-complete .mkp-ach-count,
.mkp-ach-cluster.mkp-complete .mkp-ach-xp {
  color: var(--brass-bright);
  text-shadow: 0 0 8px rgba(232, 195, 126, 0.55);
}
.mkp-ach-cluster.mkp-complete .mkp-ach-count {
  border-left-color: var(--panel-border-strong);
}

/* ---------- Bug Squash (tucked into the footer) ---------- */
.mkp-bug-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  margin-left: 10px;
  font-size: 13px;
  opacity: 0.28;
  filter: grayscale(1);
  border: none;
  background: none;
  cursor: pointer;
  vertical-align: middle;
  transition: opacity 0.2s ease, filter 0.2s ease, transform 0.2s ease;
}
.mkp-bug-toggle:hover {
  opacity: 0.9;
  filter: grayscale(0);
  transform: scale(1.15);
}

.mkp-bug-panel {
  max-width: var(--max-w, 1180px);
  margin: 0 auto;
  padding: 0 var(--gutter, 24px);
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  transition: max-height 0.45s ease, opacity 0.35s ease, padding-bottom 0.45s ease;
}
.mkp-bug-panel.mkp-open {
  max-height: 420px;
  opacity: 1;
  padding-bottom: 40px;
}
/* Brief highlight once the page finishes auto-scrolling to the panel,
   so "you found it" reads as a moment, not just a silent scroll. */
.mkp-bug-panel.mkp-pulse .mkp-bug-inner { animation: mkpPulseGlow 0.9s ease; }
@keyframes mkpPulseGlow {
  0% { box-shadow: 0 0 0 0 rgba(232, 195, 126, 0); border-color: var(--panel-border-strong); }
  30% { box-shadow: 0 0 0 4px rgba(232, 195, 126, 0.25); border-color: var(--brass); }
  100% { box-shadow: 0 0 0 0 rgba(232, 195, 126, 0); border-color: var(--panel-border-strong); }
}
.mkp-bug-inner {
  border: 1px dashed var(--panel-border-strong);
  border-radius: var(--radius-md);
  background: var(--panel-2);
  padding: 18px;
  margin-top: 4px;
}
.mkp-bug-label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 10px;
}
.mkp-bug-hud {
  display: flex;
  gap: 16px;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-muted);
  margin-bottom: 10px;
}
.mkp-bug-hud b { color: var(--brass-bright); font-weight: 600; }
.mkp-bug-stage {
  position: relative;
  width: 100%;
  height: 210px;
  background: var(--bg-soft);
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 14px;
}
.mkp-bug {
  position: absolute;
  font-size: 24px;
  cursor: pointer;
  user-select: none;
  filter: drop-shadow(0 4px 6px rgba(0,0,0,0.4));
  animation: mkpBugBob 1.3s ease-in-out infinite;
  transition: transform 0.18s ease, opacity 0.18s ease;
}
.mkp-bug:hover { transform: scale(1.18); }
.mkp-bug.mkp-squashed { transform: scale(0.2) rotate(30deg); opacity: 0; }
@keyframes mkpBugBob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
.mkp-bug-plus {
  position: absolute;
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 13px;
  color: var(--brass-bright);
  pointer-events: none;
  animation: mkpPlusFloat 0.7s ease forwards;
}
@keyframes mkpPlusFloat { 0% { opacity: 1; transform: translateY(0); } 100% { opacity: 0; transform: translateY(-24px); } }
.mkp-bug-result {
  position: absolute;
  inset: 0;
  background: rgba(18,10,30,0.92);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  text-align: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
  padding: 16px;
}
.mkp-bug-result.mkp-open { opacity: 1; pointer-events: auto; }
.mkp-bug-result .mkp-rank { font-family: var(--font-display); font-weight: 600; font-size: 17px; color: var(--ink); }
.mkp-bug-result .mkp-score { font-family: var(--font-mono); color: var(--ink-muted); font-size: 12.5px; }

/* ---------- Mobile die rail — the same real Three.js d20 as the
   desktop scroll rail, riding a vertical track of slots inset into
   the hamburger dropdown's (#navLinks, see features.js "4. MOBILE
   ROLL THE DIE") own left gutter, one slot per category, sliding to
   whichever one is active. Only shown below 760px, the exact
   breakpoint where the site's own hamburger button (".nav-toggle" in
   style.css) takes over from the plain nav links — the same width
   range where the desktop rail has no room to exist either (hidden
   below 1500px). Hidden by default so it never doubles up with the
   real one above 760px. */
/* 58px gutter: sized to fit the die's grown-while-showing-a-result
   width (54px) plus a small buffer either side, so that pop doesn't
   clip against or overlap the category text — see GROW_DIE_PX in
   features.js. Rail sits centered inside that gutter (left:16px, rail
   itself 26px wide → center at 29px = 58/2). */
@media (max-width: 760px) {
  #navLinks.mkp-has-mobile-rail { padding-left: 58px; }
}

.mkp-mobile-rail { display: none; }
@media (max-width: 760px) {
  .mkp-mobile-rail {
    display: block;
    position: absolute;
    left: 16px;
    top: 10px;
    bottom: 18px;
    width: 26px;
  }
}
.mkp-mobile-rail-track { position: relative; height: 100%; }
.mkp-mobile-slot {
  position: absolute;
  left: 50%;
  width: 8px;
  height: 8px;
  margin-left: -4px;
  border-radius: 50%;
  background: transparent;
  border: 1px solid var(--panel-border-strong);
  transition: background 0.2s ease, border-color 0.2s ease, opacity 0.2s ease;
}
.mkp-mobile-slot.current { opacity: 0; }
.mkp-mobile-slot.passed { background: var(--brass-dim); border-color: var(--brass); }

.mkp-mobile-die-3d {
  position: absolute;
  left: 50%;
  width: 26px;
  height: 26px;
  margin-left: -13px;
  /* flex + centered child is what lets the canvas grow past this box's
     own 26px bounds symmetrically (see GROW_DIE_PX in features.js)
     instead of overflowing off just one corner — same trick the
     desktop rail's own ".rail-die" uses in style.css. */
  display: flex;
  align-items: center;
  justify-content: center;
  transition: top 0.5s cubic-bezier(.2,.8,.2,1);
  pointer-events: auto;
  cursor: pointer;
}
.mkp-mobile-die-3d.mkp-die-moving { pointer-events: none; }
.mkp-mobile-die-3d:focus-visible {
  outline: 2px solid var(--brass-bright);
  outline-offset: 4px;
  border-radius: 50%;
}
.mkp-mobile-die-3d canvas {
  width: 26px;
  height: 26px;
  display: block;
  filter: drop-shadow(0 0 8px rgba(232, 195, 126, 0.5));
  /* Pops between 26px (idle/tumbling) and 54px (while a rolled result
     is showing) instead of jump-cutting — see setDieSize() in
     features.js, same idea as the desktop die. */
  transition: width 0.28s cubic-bezier(0.22, 0.85, 0.25, 1), height 0.28s cubic-bezier(0.22, 0.85, 0.25, 1);
}

/* Quick "can't do that right now" shake — same trigger as the desktop
   die: every click while busy, AND clicks SILENT_CLICKS+1..
   CLICKS_TO_ROLL-1 of an otherwise-idle click streak (see features.js). */
@keyframes mkpMobileDieShake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-3px); }
  75% { transform: translateX(3px); }
}
.mkp-mobile-die-3d.mkp-die-shake canvas {
  animation: mkpMobileDieShake 0.22s ease;
}

@media (max-width: 760px) and (prefers-reduced-motion: reduce) {
  .mkp-mobile-die-3d { transition: none; }
  .mkp-mobile-die-3d canvas { transition: none; }
}

/* ---------- Fallback "Roll the die" button — same spot the flat
   emoji version lived before this became the real 3D rail; only
   built (see features.js) if Three.js failed to load or WebGL init
   threw, so the achievement stays reachable either way. ---------- */
.mkp-mobile-die-row { display: none; }

@media (max-width: 760px) {
  .mkp-mobile-die-row {
    display: flex;
    justify-content: center;
    padding: 8px 10px 4px;
  }
  .mkp-mobile-die {
    display: flex;
    align-items: center;
    gap: 8px;
    background: var(--panel-2);
    border: 1px dashed var(--panel-border-strong);
    border-radius: 10px;
    padding: 8px 16px;
    font-family: var(--font-mono);
    font-size: 12.5px;
    color: var(--ink-muted);
    cursor: pointer;
    transition: border-color 0.2s ease, color 0.2s ease, transform 0.15s ease;
  }
  .mkp-mobile-die:active { transform: scale(0.96); }
  .mkp-mobile-die-face { font-size: 18px; line-height: 1; }
  .mkp-mobile-die.mkp-rolling .mkp-mobile-die-face { animation: mkpDieSpin 0.5s linear infinite; }
  .mkp-mobile-die.mkp-rolled {
    border-color: var(--brass);
    border-style: solid;
    color: var(--brass-bright);
  }
}
@keyframes mkpDieSpin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
@media (max-width: 760px) and (prefers-reduced-motion: reduce) {
  .mkp-mobile-die.mkp-rolling .mkp-mobile-die-face { animation: none; }
}
