:root {
  --bg-color: #fff2d6;
  --text-color: #ffffff;
  --accent-color: #3498db;
  --cell-size: 50px;  /* initial fallback; overridden by JS */
  --grid-gap: 12px;   /* initial fallback; overridden by JS */
  --board-bg: #4a2c1a; /* Dark brown wood color */
  --shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
  --fill-color: #fff2d6; /* Very dark purple for side fills */

  --cell-empty: #535353;
  --cell-red: #cd2c1a;
  --cell-yellow: #f1c40f;

  --cell-fixed-border: 3px solid rgba(0, 0, 0, 0.2);

  /* ─── Board tuning ────────────────────────────────────────────
     Nudge the board relative to the background art.
     Values are percentages of the board's own size, so they
     scale proportionally with the viewport and zoom level.
     Positive X = right, positive Y = down.                      */
  --board-offset-x: 0%;
  --board-offset-y: 0%;
  /* Gap between cells as a fraction of cell size (0.25 = 25%).
     Higher = more spacing, lower = tighter grid.                */
  --board-gap-ratio: 0.50;
  /* Edge padding as a fraction of board size (0.05 = 5%).
     Consistent margin around the grid regardless of grid size.  */
  --board-edge-padding: 0.05;
  /* Ghost circle size as a fraction of cell size (0.8 = 80%).
     Shown at 2×2 violations.                                    */
  --ghost-size-ratio: 1.0;
  /* Board size as a fraction of the background image (0.55 = 55%).
     Higher = larger board, lower = smaller board.               */
  --board-fit-ratio: 0.58;
  --scene-scale: 1.37;
  --scene-offset-y: 3.5%;
}

/* Portrait background offset (override if needed) */
#app.background-tall {
  --board-offset-x: 0%;
  --board-offset-y: 0%;
  --board-fit-ratio: 0.55;
}

/* Landscape background offset (override if needed) */
#app.background-wide {
  --board-offset-x: 0%;
  --board-offset-y: 0%;
  --board-fit-ratio: 0.55;
}

html {
  overflow: hidden;
  height: 100%;
  background-color: var(--bg-color);
}

body {
  margin: 0;
  font-family: 'Outfit', sans-serif;
  background-color: var(--bg-color);
  color: var(--text-color);
  min-height: 100vh;
  height: 100vh;
  overflow: hidden;
  position: fixed;
  width: 100%;
  -webkit-overflow-scrolling: touch;
}

#app {
  min-height: 100vh;
  height: 100vh;
  width: 100vw;
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--fill-color); /* Very dark purple fill */
}

#app.no-background .game-background {
  background-image: none;
}

/* Game scene: wraps background + board so they scale together as a unit.
   Gameplay uses a slightly tighter camera plus a small downward nudge;
   .zoom-out reverts to the neutral framing on win.
   #app has overflow:hidden so the 10% that bleeds past each edge is cleanly cropped. */
#game-scene {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  transform: translateY(var(--scene-offset-y)) scale(var(--scene-scale));
  transform-origin: center center;
  transition: transform 0.8s ease-in-out;
}

#app:not(.game-started) #game-scene {
  z-index: 4;
}

@keyframes title-screen-fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* Title fade only after Congratulations! — class added in showOpeningScreenFromFinale() */
#app.title-screen-reenter-from-finale:not(.game-started) .start-game-overlay:not(.hidden),
#app.title-screen-reenter-from-finale:not(.game-started) .start-game-cta:not(.hidden) {
  animation: title-screen-fade-in 0.55s ease-out both;
}

@media (prefers-reduced-motion: reduce) {
  #app.title-screen-reenter-from-finale:not(.game-started) .start-game-overlay:not(.hidden),
  #app.title-screen-reenter-from-finale:not(.game-started) .start-game-cta:not(.hidden) {
    animation: none;
    opacity: 1;
  }
}

#app.zoom-out #game-scene {
  transform: translateY(0) scale(1);
}

/* Used when snapping back to gameplay zoom instantly (level load / reset) */
#app.no-scene-transition #game-scene {
  transition: none;
}

.start-game-cta {
  --start-cta-scale: 1;
  position: absolute;
  left: 50%;
  top: 50%;
  width: 680px;
  padding-top: 330px;
  transform: translate(-50%, -50%) scale(var(--start-cta-scale));
  transform-origin: center center;
  z-index: 8;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  transition: opacity 0.18s ease;
}

.start-game-cta.hidden {
  opacity: 0;
  pointer-events: none;
}

.start-game-logos {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 14px;
  z-index: 1;
  pointer-events: none;
}

.start-game-logo {
  height: auto;
  display: block;
}

.start-game-logo-playmath {
  width: 220px;
  filter: brightness(0);
}

.start-game-logo-mathopolis {
  width: 180px;
}

.start-game-logo-separator {
  color: #000000;
  font-size: 58px;
  font-weight: 400;
  line-height: 1;
}

.start-game-icon {
  position: absolute;
  top: 110px;
  left: 50%;
  transform: translateX(-50%) rotate(-3deg);
  width: 300px;
  height: auto;
  border: 8px solid #000000;
  border-radius: 28px;
  box-shadow:
    0 0 0 8px #ffcc00,
    0 0 20px rgba(255, 255, 255, 0.78);
  z-index: 0;
  pointer-events: none;
}

.start-game-title {
  position: relative;
  width: 680px;
  height: auto;
  display: block;
  filter: drop-shadow(0 8px 10px rgba(0, 0, 0, 0.45));
  z-index: 2;
}

.start-game-btn {
  position: relative;
  margin-top: 16px;
  min-width: 14rem;
  padding: 0.9rem 1.8rem;
  border: 4px solid #000000;
  border-radius: 999px;
  background: #22c55e;
  color: #000000;
  font-family: inherit;
  font-size: 2.6rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  cursor: pointer;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
  transform: scale(1);
  transition: transform 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease, opacity 0.18s ease;
  animation: glowPulse 2s ease-in-out infinite;
  z-index: 3;
}

.start-game-btn:hover {
  background: #4ade80;
  transform: scale(1.05);
  border-color: #000000;
}

.start-game-btn:active {
  transform: scale(1);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
}

.start-game-btn.hidden {
  opacity: 0;
  pointer-events: none;
}

@media (max-width: 1024px), (max-height: 860px) {
  .start-game-cta {
    --start-cta-scale: 0.9;
  }
}

@media (max-width: 860px), (max-height: 760px) {
  .start-game-cta {
    --start-cta-scale: 0.78;
  }
}

@media (max-width: 700px), (max-height: 680px) {
  .start-game-cta {
    --start-cta-scale: 0.66;
  }
}

@media (max-width: 560px), (max-height: 620px) {
  .start-game-cta {
    --start-cta-scale: 0.56;
  }
}

.start-game-overlay {
  position: absolute;
  inset: 0;
  z-index: 7;
  pointer-events: auto;
  background: rgba(255, 242, 214, 0.70);
  backdrop-filter: blur(14px) saturate(0.85);
  transition: opacity 0.22s ease;
}

.start-game-overlay.hidden {
  opacity: 0;
  pointer-events: none;
}

/* Game background: board image layer (above banners, below board).
   position:absolute instead of fixed so it lives inside #game-scene and scales with it. */
.game-background {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background-image: url(../res/new/board_vertical.png);
  background-size: 100% auto; /* Width matches viewport, height scales proportionally */
  background-position: center;
  background-repeat: no-repeat;
}

#app.background-wide .game-background {
  background-image: url(../res/new/board_horizontal.png);
  background-size: auto 100%; /* Height matches viewport, width scales proportionally */
}

/* Banners: above the board, below the fixed UI controls */
.game-banners {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 3;
  pointer-events: none;
}
.game-banners .banner {
  width: 100%;
  height: auto;
  display: block;
  vertical-align: top;
}
/* Wide (horizontal): show top_banner only */
#app.background-wide .game-banners .banner-tall {
  display: none;
}
#app.background-wide .game-banners .banner-wide {
  display: block;
  max-width: var(--banner-max-width, 100%);
  margin-left: auto;
  margin-right: auto;
}
/* Tall (portrait): show big_banner only; image fills width, height scales proportionally */
#app.background-tall .game-banners .banner-wide {
  display: none;
}
#app.background-tall .game-banners .banner-tall {
  display: block;
}

/* Top controls */
.top-controls {
  position: fixed;
  top: 1rem;
  z-index: 100;
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  opacity: 1;
  transform: translateY(0);
  transition: opacity 0.18s ease, transform 0.18s ease;
}

#app:not(.game-started) .top-controls {
  opacity: 0;
  transform: translateY(-6px);
  pointer-events: none;
}

.top-controls-left {
  left: 1rem;
}

.top-controls-right {
  right: 1rem;
}

.control-btn {
  min-width: 3.5rem;
  height: 3.5rem;
  padding: 0 1rem;
  border: 4px solid #000000;
  border-radius: 999px;
  background: #fedb00;
  color: #000000;
  font-family: inherit;
  font-size: 1.05rem;
  font-weight: 700;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.2s ease, background 0.2s ease, box-shadow 0.2s ease;
  box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3);
}

.control-btn:hover {
  transform: scale(1.05);
  border-color: #000000;
}

.top-controls .control-btn:active:not(:disabled) {
  background: #c9ac00;
}

.control-btn:focus-visible {
  outline: 3px solid rgba(0, 0, 0, 0.85);
  outline-offset: 2px;
  box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.3);
  animation: kb-btn-pulse 1.8s ease-in-out infinite, kb-fade-in 0.15s ease-out;
}

.level-select-btn {
  min-width: 7.7rem;
  padding-inline: 1.1rem 0.95rem;
  letter-spacing: 0.02em;
  justify-content: center;
  gap: 0.46rem;
  font-size: 1.12rem;
  white-space: nowrap;
}

.level-select-chevron {
  width: 0.55rem;
  height: 0.55rem;
  flex: 0 0 auto;
  border-right: 0.2rem solid currentColor;
  border-bottom: 0.2rem solid currentColor;
  transform: translateY(-0.1rem) rotate(45deg);
  transition: transform 0.2s ease;
}

.level-select-btn[aria-expanded="true"] .level-select-chevron {
  transform: translateY(0.08rem) rotate(-135deg);
}

.reset-btn {
  width: 3.5rem;
  padding: 0;
}

.undo-btn {
  width: 3.5rem;
  padding: 0;
}

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

.undo-btn:disabled:hover {
  transform: none;
}

.reset-icon {
  width: 1.5rem;
  height: 1.5rem;
  display: block;
  stroke: currentColor;
  stroke-width: 2.8;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  transform: translateX(0.03rem);
}

.undo-icon {
  width: 1.5rem;
  height: 1.5rem;
  display: block;
  stroke: currentColor;
  stroke-width: 2.8;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  transform: translateY(-0.2rem);
}

.options-btn {
  width: 3.5rem;
  padding: 0;
  gap: 0.3rem;
}

.options-dot {
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 999px;
  background: currentColor;
  display: block;
}

@keyframes kb-btn-pulse {
  0%, 100% { outline-color: rgba(0, 0, 0, 0.85); box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.3); }
  50%      { outline-color: rgba(0, 0, 0, 0.45); box-shadow: 0 0 6px 2px rgba(0, 0, 0, 0.15); }
}

/* Level modal */
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(18, 8, 36, 0.62);
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
  backdrop-filter: blur(6px);
}

.modal-overlay.active {
  opacity: 1;
  pointer-events: all;
}

.modal-panel {
  position: relative;
  width: min(28rem, calc(100vw - 2rem));
  max-height: min(80vh, 36rem);
  overflow-y: auto;
  padding: 1.75rem 1.5rem 1.5rem;
  border: 8px solid #000000;
  border-radius: 22px;
  background:
    linear-gradient(180deg, rgba(255, 238, 187, 0.96) 0%, rgba(255, 216, 117, 0.96) 100%);
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.45);
  scrollbar-width: thin;
  scrollbar-color: rgba(73, 38, 0, 0.55) transparent;
}

.modal-panel::-webkit-scrollbar {
  width: 7px;
}

.modal-panel::-webkit-scrollbar-track {
  background: transparent;
}

.modal-panel::-webkit-scrollbar-thumb {
  background: rgba(73, 38, 0, 0.55);
  border-radius: 999px;
}

.modal-panel h2 {
  margin: 0;
  padding-right: 3rem;
  color: #3f1f00;
  font-size: 1.6rem;
}

.modal-close {
  position: absolute;
  top: 0.75rem;
  right: 1rem;
  background: none;
  border: 0;
  padding: 0;
  font-size: 2.4rem;
  font-weight: 700;
  cursor: pointer;
  color: #3f1f00;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  transition: transform 0.2s ease, color 0.2s ease;
}

.modal-close:hover {
  transform: scale(1.05);
  color: #140600;
}

.level-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(4.1rem, 1fr));
  gap: 0.7rem;
  margin-top: 1.4rem;
}

.level-item {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 3.6rem;
  border: 4px solid #8a6b2a;
  background: #f5df9e;
  border-radius: 999px;
  cursor: pointer;
  font-family: inherit;
  font-size: 1.05rem;
  font-weight: 700;
  color: #553600;
  transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}

.level-item[data-state="unsolved"] {
  border-color: #8a6b2a;
  background: #f5df9e;
  color: #553600;
}

.level-item[data-state="unsolved"]:hover {
  background: #fae8b5;
}

.level-item[data-state="solved"] {
  border-color: #2f7d41;
  background: #d8f7bf;
  color: #1b5627;
  padding-right: 0.9rem;
}

.level-item[data-state="current-solved"] {
  border-color: #000000;
  background: #d8f7bf;
  color: #1b5627;
  padding-right: 0.9rem;
}

.level-item[data-state="solved"]::after,
.level-item[data-state="current-solved"]::after {
  content: '✓';
  position: absolute;
  top: 0.42rem;
  right: 0.42rem;
  width: 1rem;
  height: 1rem;
  border-radius: 999px;
  background: #1f6a34;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.68rem;
  line-height: 1;
  font-weight: 900;
  color: #ffffff;
}

.level-item[data-state="solved"]:hover,
.level-item[data-state="current-solved"]:hover {
  background: #e6fbd4;
}

.level-item[data-state="current"] {
  border-color: #000000;
  background: #f5df9e;
  color: #553600;
}

.level-item[data-state="current"]:hover {
  background: #fae8b5;
}

.level-item:focus-visible {
  outline: 3px solid rgba(63, 31, 0, 0.9);
  outline-offset: 2px;
  animation: kb-fade-in 0.15s ease-out;
}

.modal-close:focus-visible,
.options-menu .audio-toggle:focus-visible {
  outline: 3px solid rgba(63, 31, 0, 0.9);
  outline-offset: 2px;
  box-shadow: 0 0 10px 3px rgba(63, 31, 0, 0.25);
  animation: kb-btn-pulse 1.8s ease-in-out infinite, kb-fade-in 0.15s ease-out;
}

/* Sound dropdown */
.options-menu {
  position: absolute;
  top: calc(100% + 0.65rem);
  right: 0;
  min-width: 11rem;
  display: grid;
  gap: 0.75rem;
  padding: 0.9rem;
  border: 4px solid #000000;
  border-radius: 16px;
  background: rgba(42, 26, 60, 0.98);
  color: #ffffff;
  box-shadow: 0 14px 28px rgba(0, 0, 0, 0.32);
  opacity: 0;
  pointer-events: none;
  transform: translateY(-0.35rem) scale(0.96);
  transform-origin: top right;
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.options-menu.active {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0) scale(1);
}

.options-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

.options-label {
  font-size: 1rem;
  font-weight: 600;
}

.audio-toggle {
  flex-shrink: 0;
  width: 3.45rem;
  height: 2rem;
  border: 4px solid #000;
  border-radius: 999px;
  font-size: 0.74rem;
  font-weight: 700;
  cursor: pointer;
  transition: background 0.15s;
  color: #000;
  background: #fedb00;
}

.audio-toggle.off {
  background: #5d5d5d;
  color: #f4f4f4;
}

.audio-toggle:hover {
  transform: scale(1.05);
}

@keyframes kb-menu-pulse {
  0%, 100% { outline-color: rgba(255, 255, 255, 0.9); box-shadow: 0 0 10px 3px rgba(255, 255, 255, 0.35); }
  50%      { outline-color: rgba(255, 255, 255, 0.55); box-shadow: 0 0 6px 2px rgba(255, 255, 255, 0.15); }
}

@media (max-width: 480px) {
  .top-controls {
    top: 0.75rem;
    gap: 0.55rem;
  }

  .top-controls-left {
    left: 0.75rem;
  }

  .top-controls-right {
    right: 0.75rem;
  }

  .control-btn {
    height: 3.15rem;
    min-width: 3.15rem;
    border-width: 3px;
    border-radius: 999px;
  }

  .level-select-btn {
    min-width: 6.8rem;
    padding-inline: 0.95rem 0.8rem;
    font-size: 1rem;
  }

  .undo-btn {
    width: 3.15rem;
  }

  .reset-btn,
  .options-btn {
    width: 3.15rem;
  }

  .modal-panel {
    width: min(24rem, calc(100vw - 1rem));
    padding: 1.35rem 1rem 1rem;
    border-width: 6px;
    border-radius: 18px;
  }

  .modal-panel h2 {
    font-size: 1.35rem;
  }

  .level-list {
    grid-template-columns: repeat(auto-fit, minmax(3.4rem, 1fr));
    gap: 0.55rem;
  }

  .level-item {
    min-height: 3.2rem;
  }

  .level-item[data-state="solved"]::after,
  .level-item[data-state="current-solved"]::after {
    top: 0.34rem;
    right: 0.34rem;
    width: 0.88rem;
    height: 0.88rem;
    font-size: 0.58rem;
  }
}

.board {
  display: grid;
  gap: var(--grid-gap);
  /* background-color: var(--board-bg); */
  padding: var(--board-padding, 12px);
  box-sizing: border-box; /* padding inside boardSize so total size is constant across grid sizes */
  /* border-radius: 16px; */
  /* border: 2px solid #000000; Black outline */
  aspect-ratio: 1;
  position: relative;
  z-index: 2; /* Below banner overlay, below menu buttons */
  /* Board dimensions are set dynamically via JavaScript to maintain consistent size across levels */
  /* Performance optimizations - isolate layout from rest of page */
  contain: layout style;
  isolation: isolate;
  /* Shift board position relative to background art (tuned via custom properties) */
  translate: var(--board-offset-x, 0%) var(--board-offset-y, 0%);
  /* Prevent text/object selection on double-click */
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}

.tentacle-overlay {
  overflow: visible;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 2; /* Above rings/blank cells, below tokens */
  /* Prevent rendering artifacts from 3D transforms on tokens */
  will-change: transform;
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
  /* Create a new stacking context to avoid interference from token 3D transforms */
  isolation: isolate;
}

/* Subtle random shake for creatures in 2x2 violation (delay set per token in JS) */
@keyframes violationShake {
  0%, 100% { transform: translate(0, 0); }
  25% { transform: translate(0.5px, -0.25px); }
  50% { transform: translate(-0.25px, 0.5px); }
  75% { transform: translate(-0.5px, 0.25px); }
}

.cell.token.violation-shake {
  animation: violationShake 0.15s ease-in-out infinite;
}

.tentacle {
  stroke-linecap: round;
  transition: opacity 0.2s;
  transform-origin: center;
  /* Prevent rendering artifacts */
  image-rendering: auto;
  will-change: auto;
  backface-visibility: hidden;
  -webkit-font-smoothing: antialiased;
}

.tentacle.bounce {
  animation: tentacleBounce var(--bounce-duration, 0.6s) ease-in-out infinite;
  animation-delay: var(--bounce-delay, 0s);
}

/* Confetti overlay during win celebration */
.confetti-container {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 50;
  overflow: hidden;
}

.confetti-piece {
  position: absolute;
  width: 24px;
  height: 24px;
  top: -30px;
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
  animation: confettiFall var(--confetti-duration, 4s) linear forwards;
  animation-delay: var(--confetti-delay, 0s);
  opacity: 0.95;
  will-change: transform;
}

@keyframes confettiFall {
  0% {
    transform: translate(var(--confetti-start-x, 0), 0) rotate(var(--confetti-start-rot, 0deg));
    opacity: 0.95;
  }
  100% {
    transform: translate(var(--confetti-end-x, 0), 100vh) rotate(var(--confetti-end-rot, 720deg));
    opacity: 0.7;
  }
}

/* Tentacle color classes removed - colors are now set via fill attribute on circles */

.ghost-character {
  /* Container for ghost bug - no pulsing animation (removed) */
  position: relative;
  /* Performance optimizations */
  contain: layout style;
}

/* Bug inside ghost character uses the same scurry animation as gremlin */
.ghost-character .ghost-bug {
  animation: scurry var(--animation-duration, 3s) ease-in-out infinite;
  animation-delay: var(--animation-delay, 0s);
  /* Performance optimizations for Chrome */
  will-change: transform;
  contain: layout style;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.cell {
  width: var(--cell-size);
  height: var(--cell-size);
  background-color: var(--cell-empty);
  border-radius: 50%;
  cursor: pointer;
  position: relative;
  transition: filter 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94);
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1);
  contain: layout style paint;
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}

/* Keyboard cursor — standalone absolutely-positioned element inside the board.
   Fully independent of cell DOM so it avoids cropping/overflow/shape issues. */
.kb-cursor {
  position: absolute;
  box-sizing: border-box;
  border-radius: 50%;
  border: 3px solid rgba(255, 255, 255, 0.9);
  box-shadow: 0 0 12px 4px rgba(255, 255, 255, 0.4);
  pointer-events: none;
  z-index: 20;
  opacity: 0;
}

.kb-cursor.visible {
  animation: kb-cursor-appear 0.15s ease-out forwards, kb-pulse 1.8s ease-in-out 0.15s infinite;
}

@keyframes kb-cursor-appear {
  from { opacity: 0; transform: scale(0.7); }
  to   { opacity: 1; transform: scale(1); }
}

@keyframes kb-pulse {
  0%, 100% { border-color: rgba(255, 255, 255, 0.9); box-shadow: 0 0 12px 4px rgba(255, 255, 255, 0.4); }
  50%      { border-color: rgba(255, 255, 255, 0.55); box-shadow: 0 0 8px 2px rgba(255, 255, 255, 0.2); }
}

@keyframes kb-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.cell.blank {
  background-color: transparent;
  cursor: pointer;
  z-index: 1;
  pointer-events: auto;
  /* Only transition interactive visual properties, NOT layout ones (width/height/etc.)
     so that resizeBoard() updates take effect instantly with no easing lag. */
  transition: box-shadow 0.2s ease;
  position: relative;
  border: none;
  box-sizing: border-box;
  box-shadow: none;
}

/* Bacteria in empty cells (below the hole, visible within it) */
.cell.blank .cell-bacteria.gremlin {
  position: absolute;
  width: 60%;
  height: 60%;
  top: 20%;
  left: 20%;
  z-index: 0;
  pointer-events: none;
  background-image: url(../res/new/bacteria.png);
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
  opacity: 1;
  transform-origin: center center;
  animation: scurry var(--animation-duration, 3s) ease-in-out infinite;
  animation-delay: var(--animation-delay, 0s);
  will-change: transform;
  contain: layout style;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

/* Hole graphic layered above bacteria */
.cell.blank .cell-hole {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  pointer-events: none;
  background-image: url(../res/new/hole.png);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
/* Hide hole when a creature (fixed or player-placed) covers this cell */
.cell.blank.occupied .cell-hole {
  display: none;
}

/* Hide bacteria and stop their animation when hole is covered (performance) */
.cell.blank.occupied .cell-bacteria {
  display: none;
  animation: none;
}

@keyframes scurry {
  0% {
    transform: translate(0, 0) rotate(var(--initial-rotation, 0deg));
  }
  /* Rotate to direction 1 (0° from up) */
  5% {
    transform: translate(0, 0) rotate(calc(var(--initial-rotation, 0deg) + 0deg));
  }
  /* Move in direction 1 (calculated based on initial rotation) */
  15% {
    transform: translate(var(--move-1-x, 0px), var(--move-1-y, -4px)) rotate(calc(var(--initial-rotation, 0deg) + 0deg));
  }
  /* Rotate to direction 2 (60° from up) */
  20% {
    transform: translate(var(--move-1-x, 0px), var(--move-1-y, -4px)) rotate(calc(var(--initial-rotation, 0deg) + 60deg));
  }
  /* Move in direction 2 (cumulative) */
  30% {
    transform: translate(calc(var(--move-1-x, 0px) + var(--move-2-x, 3.5px)), calc(var(--move-1-y, -4px) + var(--move-2-y, -2px))) rotate(calc(var(--initial-rotation, 0deg) + 60deg));
  }
  /* Rotate to direction 3 (120° from up) */
  35% {
    transform: translate(calc(var(--move-1-x, 0px) + var(--move-2-x, 3.5px)), calc(var(--move-1-y, -4px) + var(--move-2-y, -2px))) rotate(calc(var(--initial-rotation, 0deg) + 120deg));
  }
  /* Move in direction 3 (cumulative) */
  45% {
    transform: translate(calc(var(--move-1-x, 0px) + var(--move-2-x, 3.5px) + var(--move-3-x, 3.5px)), calc(var(--move-1-y, -4px) + var(--move-2-y, -2px) + var(--move-3-y, 2px))) rotate(calc(var(--initial-rotation, 0deg) + 120deg));
  }
  /* Rotate to direction 4 (180° from up) */
  50% {
    transform: translate(calc(var(--move-1-x, 0px) + var(--move-2-x, 3.5px) + var(--move-3-x, 3.5px)), calc(var(--move-1-y, -4px) + var(--move-2-y, -2px) + var(--move-3-y, 2px))) rotate(calc(var(--initial-rotation, 0deg) + 180deg));
  }
  /* Move in direction 4 (cumulative) */
  60% {
    transform: translate(calc(var(--move-1-x, 0px) + var(--move-2-x, 3.5px) + var(--move-3-x, 3.5px) + var(--move-4-x, 0px)), calc(var(--move-1-y, -4px) + var(--move-2-y, -2px) + var(--move-3-y, 2px) + var(--move-4-y, 4px))) rotate(calc(var(--initial-rotation, 0deg) + 180deg));
  }
  /* Rotate to direction 5 (240° from up) */
  65% {
    transform: translate(calc(var(--move-1-x, 0px) + var(--move-2-x, 3.5px) + var(--move-3-x, 3.5px) + var(--move-4-x, 0px)), calc(var(--move-1-y, -4px) + var(--move-2-y, -2px) + var(--move-3-y, 2px) + var(--move-4-y, 4px))) rotate(calc(var(--initial-rotation, 0deg) + 240deg));
  }
  /* Move in direction 5 (cumulative) */
  75% {
    transform: translate(calc(var(--move-1-x, 0px) + var(--move-2-x, 3.5px) + var(--move-3-x, 3.5px) + var(--move-4-x, 0px) + var(--move-5-x, -3.5px)), calc(var(--move-1-y, -4px) + var(--move-2-y, -2px) + var(--move-3-y, 2px) + var(--move-4-y, 4px) + var(--move-5-y, 2px))) rotate(calc(var(--initial-rotation, 0deg) + 240deg));
  }
  /* Rotate to direction 6 (300° from up) */
  80% {
    transform: translate(calc(var(--move-1-x, 0px) + var(--move-2-x, 3.5px) + var(--move-3-x, 3.5px) + var(--move-4-x, 0px) + var(--move-5-x, -3.5px)), calc(var(--move-1-y, -4px) + var(--move-2-y, -2px) + var(--move-3-y, 2px) + var(--move-4-y, 4px) + var(--move-5-y, 2px))) rotate(calc(var(--initial-rotation, 0deg) + 300deg));
  }
  /* Move in direction 6 (cumulative) */
  90% {
    transform: translate(calc(var(--move-1-x, 0px) + var(--move-2-x, 3.5px) + var(--move-3-x, 3.5px) + var(--move-4-x, 0px) + var(--move-5-x, -3.5px) + var(--move-6-x, -3.5px)), calc(var(--move-1-y, -4px) + var(--move-2-y, -2px) + var(--move-3-y, 2px) + var(--move-4-y, 4px) + var(--move-5-y, 2px) + var(--move-6-y, -2px))) rotate(calc(var(--initial-rotation, 0deg) + 300deg));
  }
  /* Rotate back to start */
  95% {
    transform: translate(calc(var(--move-1-x, 0px) + var(--move-2-x, 3.5px) + var(--move-3-x, 3.5px) + var(--move-4-x, 0px) + var(--move-5-x, -3.5px) + var(--move-6-x, -3.5px)), calc(var(--move-1-y, -4px) + var(--move-2-y, -2px) + var(--move-3-y, 2px) + var(--move-4-y, 4px) + var(--move-5-y, 2px) + var(--move-6-y, -2px))) rotate(var(--initial-rotation, 0deg));
  }
  /* Return to start */
  100% {
    transform: translate(0, 0) rotate(var(--initial-rotation, 0deg));
  }
}

.cell.blank.no-hover:hover {
  /* Suppress all hover effects during fall animation */
  box-shadow: none;
  border: none;
}

/* Disable hover on touch devices to prevent sticky hover states */
@media (hover: hover) and (pointer: fine) {
  .cell.blank:hover:not(.no-hover) {
    box-shadow: 
      inset 0 2px 4px rgba(0, 0, 0, 0.1),
      0 0 20px rgba(255, 255, 255, 0.3),
      0 0 40px rgba(255, 255, 255, 0.2);
    /* outline: 2px solid rgba(255, 255, 255, 0.4); */
    outline-offset: 0;
  }
}

/* Active state for touch devices */
.cell.blank:active:not(.no-hover) {
  box-shadow: 
    inset 0 2px 4px rgba(0, 0, 0, 0.1),
    0 0 20px rgba(255, 255, 255, 0.3),
    0 0 40px rgba(255, 255, 255, 0.2);
  /* outline: 2px solid rgba(255, 255, 255, 0.4); */
  outline-offset: 0;
}

/* Disable hover and pointer when puzzle is complete */
/* During celebration: hide bacteria and stop their animation */
.board.interaction-locked .cell {
  pointer-events: none;
}

.board.puzzle-complete .cell.blank .cell-bacteria {
  visibility: hidden;
  animation: none;
}

.board.puzzle-complete .cell.blank:hover {
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1);
  border: 2px solid #000000; /* Keep black outline */
  cursor: default;
}

.board.puzzle-complete .cell.token:not(.fixed):hover {
  transform: none;
  box-shadow: none;
  filter: none;
}

.board.puzzle-complete .cell.token.yellow:not(.fixed):hover {
  transform: none;
  box-shadow: none;
  filter: none;
}

.board.puzzle-complete .cell {
  pointer-events: none;
}

.board.puzzle-complete .cell.token {
  pointer-events: none;
}

.cell.token {
  position: absolute;
  z-index: 3;
  pointer-events: auto;
  cursor: pointer;
  /* Only animate transform (hover scale/flip) — not left/top/width/height so that
     resizeBoard() repositioning is instant with no lag. */
  transition: transform 0.2s ease;
  border-radius: 0; /* No circular masking on creatures */
  box-shadow: none;
  filter: none;
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}

/* Hover for non-fixed tokens - no glow or drop shadow.
   will-change is set here (not on the base class) so the browser only creates a
   compositing layer when the user is hovering and might click, rather than permanently
   promoting every token on the board. On Chrome this avoids the cost of compositing
   up to 36 separate GPU layers on every frame. The flip animation's own will-change
   (in .cell.flipping) handles the case where a touch user taps without hovering first. */
@media (hover: hover) and (pointer: fine) {
  .cell.token:not(.fixed):hover {
    will-change: transform;
    transform: scale(1.05);
    box-shadow: none;
    filter: none;
  }

  .cell.token.yellow:not(.fixed):hover {
    will-change: transform;
    transform: scale(1.05);
    box-shadow: none;
    filter: none;
  }
}

.cell.red {
  box-shadow: none;
  box-sizing: border-box;
  /* Background will be set via inline style with SVG */
}

.cell.yellow {
  box-shadow: none;
  box-sizing: border-box;
  /* Background will be set via inline style with SVG */
}

/* Distinguish fixed cells */
.cell.fixed {
  cursor: default;
  position: relative; /* For containing absolutely positioned overlay */
  box-sizing: border-box;
  contain: layout style;
}

/* Ensure fixed tokens maintain absolute positioning for board layout */
.cell.token.fixed {
  position: absolute; /* Override .cell.fixed for tokens */
}

/* Remove border from fixed red cells */
.cell.fixed.red {
  border: none;
  box-shadow: none;
}

/* Remove border from fixed yellow cells */
.cell.fixed.yellow {
  border: none;
  box-shadow: none;
}

/* Token image element - using img instead of background-image for Safari compatibility */
.token-img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  pointer-events: none;
  z-index: 1;
  /* No border-radius: creatures shown without circular masking */
  /* Prevent image dragging */
  -webkit-user-drag: none;
  user-select: none;
  /* Performance optimizations */
  will-change: auto;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

/* Locked slot indicator - board-level ring layer above connectors/tokens */
.locked-img {
  position: absolute;
  top: -10%;
  left: -10%;
  width: 120%;
  height: 120%;
  object-fit: contain;
  pointer-events: none;
  z-index: 4;
  -webkit-user-drag: none;
  user-select: none;
}

/* SVG tokens - faces are included in the SVG files */
.cell.red,
.cell.yellow {
  /* Background is now handled by .token-img element */
  background-image: none !important;
  background-color: transparent;
}

/* Flip Animation */
@keyframes flip {
  0% {
    transform: perspective(400px) rotateY(0deg);
  }
  50% {
    transform: perspective(400px) rotateY(90deg);
  }
  100% {
    transform: perspective(400px) rotateY(0deg);
  }
}

.cell.flipping {
  animation: flip 0.4s ease-in-out;
  transform-style: preserve-3d;
  /* Safari-specific optimizations */
  will-change: transform;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.cell.flipping-reverse {
  animation: flip 0.4s ease-in-out reverse;
  transform-style: preserve-3d;
  will-change: transform;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

/* Ensure the img inside a flipping cell also flips properly */
.cell.flipping .token-img,
.cell.flipping-reverse .token-img {
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

/* Shake Animation */
@keyframes shake {
  0% {
    transform: translate(1px, 1px) rotate(0deg);
  }

  10% {
    transform: translate(-1px, -2px) rotate(-1deg);
  }

  20% {
    transform: translate(-3px, 0px) rotate(1deg);
  }

  30% {
    transform: translate(3px, 2px) rotate(0deg);
  }

  40% {
    transform: translate(1px, -1px) rotate(1deg);
  }

  50% {
    transform: translate(-1px, 2px) rotate(-1deg);
  }

  60% {
    transform: translate(-3px, 1px) rotate(0deg);
  }

  70% {
    transform: translate(3px, 1px) rotate(-1deg);
  }

  80% {
    transform: translate(-1px, -1px) rotate(1deg);
  }

  90% {
    transform: translate(1px, 2px) rotate(0deg);
  }

  100% {
    transform: translate(1px, -2px) rotate(-1deg);
  }
}

.shake {
  animation: shake 0.5s;
  animation-iteration-count: 1;
}

/* Falling Animation for fixed pieces on load */
@keyframes fall {
  0% {
    transform: translateY(-100vh);
    opacity: 0;
  }
  60% {
    opacity: 1;
  }
  100% {
    transform: translateY(0);
    opacity: 1;
  }
}

.cell.falling {
  animation: fall 0.8s cubic-bezier(0.55, 0.055, 0.675, 0.19);
  animation-fill-mode: both;
}

/* Tentacle bounce animation */
@keyframes tentacleBounce {
  0%, 100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(calc(-1 * var(--bounce-height, 6px)));
  }
}

/* Bounce Animation for celebration */
@keyframes bounce {
  0%, 100% {
    transform: translateY(0) scale(1);
  }
  25% {
    transform: translateY(calc(-1 * var(--bounce-height, 6px))) scale(1.05);
  }
  50% {
    transform: translateY(0) scale(1);
  }
  75% {
    transform: translateY(calc(-0.5 * var(--bounce-height, 6px))) scale(1.02);
  }
}

.cell.bounce {
  animation: bounce var(--bounce-duration, 0.6s) ease-in-out;
  animation-delay: var(--bounce-delay, 0s);
  animation-iteration-count: infinite;
  /* Ensure pseudo-elements (faces) move with the cell */
  transform-origin: center center;
}

/* Prevent blank cells from bouncing */
.cell.blank.bounce {
  animation: none;
}

.controls {
  display: flex;
  gap: 1rem;
  justify-content: center;
  margin-bottom: 1rem;
}

.btn-icon {
  background: rgba(255, 255, 255, 0.1);
  border: 2px solid rgba(255, 255, 255, 0.2);
  border-radius: 50%;
  width: 2.5rem;
  height: 2.5rem;
  font-size: 1.5rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.2s;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
  color: var(--text-color);
}

.btn-icon:hover {
  background: rgba(255, 255, 255, 0.2);
  transform: scale(1.05);
  border-color: rgba(255, 255, 255, 0.3);
}

.btn-icon:active {
  transform: scale(0.95);
}

/* Next Level Button */
.next-level-btn {
  position: fixed;
  bottom: 4.25rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 200;
  background: #22c55e;
  border: 4px solid #000000; /* Black outline */
  color: #000000; /* Black text for contrast */
  min-width: 12.5rem;
  padding: 1.2rem 2.8rem;
  border-radius: 999px;
  font-size: 1.4rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: transform 0.2s ease, background 0.2s ease, box-shadow 0.2s ease;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
  font-family: 'Outfit', sans-serif;
  opacity: 0;
  pointer-events: none;
}

.next-level-btn.next-level-btn--finale {
  font-size: 1.95rem;
  min-width: 15rem;
  padding: 1.45rem 3rem;
  letter-spacing: 0.015em;
}

.next-level-btn.show {
  opacity: 1;
  pointer-events: all;
  animation: nextLevelEntrance 0.78s cubic-bezier(0.2, 0.9, 0.2, 1.05) forwards, glowPulse 2s ease-in-out 0.8s infinite;
}

.next-level-btn:hover {
  background: #4ade80;
  transform: translateX(-50%) translateY(-2px);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.5);
}

.next-level-btn:active {
  transform: translateX(-50%) translateY(0);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
}

.next-level-btn:focus-visible {
  outline: 3px solid rgba(0, 0, 0, 0.85);
  outline-offset: 3px;
  box-shadow: 0 0 10px 3px rgba(0, 0, 0, 0.3), 0 4px 12px rgba(0, 0, 0, 0.4);
  animation: kb-btn-pulse 1.8s ease-in-out infinite, kb-fade-in 0.15s ease-out;
}

@keyframes nextLevelEntrance {
  0% {
    opacity: 0;
    transform: translateX(-50%) translateY(140px) scale(1.22);
  }
  58% {
    opacity: 1;
    transform: translateX(-50%) translateY(-12px) scale(0.95);
  }
  78% {
    opacity: 1;
    transform: translateX(-50%) translateY(4px) scale(1.01);
  }
  100% {
    opacity: 1;
    transform: translateX(-50%) translateY(0) scale(1);
  }
}

@keyframes glowPulse {
  0%, 100% {
    background: #22c55e;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
  }
  50% {
    background: #86efac;
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.45);
  }
}

@media (max-width: 480px) {
  .next-level-btn {
    bottom: 2.5rem;
    min-width: 11rem;
    padding: 1rem 2.2rem;
    font-size: 1.25rem;
  }

  .next-level-btn.next-level-btn--finale {
    min-width: 12.5rem;
    padding: 1.15rem 2.5rem;
    font-size: 1.48rem;
  }
}

/* Prevent text selection highlighting globally */
::selection {
  background: transparent;
}

::-moz-selection {
  background: transparent;
}
