.shell-region--bottom {
  display: grid;
  place-items: center;
  min-height: calc(var(--game-controls-height) + var(--app-footer-height) + env(safe-area-inset-bottom));
  padding-bottom: calc(var(--app-footer-height) + env(safe-area-inset-bottom));
}
.game-controls {
  pointer-events: auto;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: min(500px, calc(100vw - 24px));
  min-height: 64px;
  padding: 8px 0;
}
.game-controls[hidden] { display: none !important; }
.game-control {
  min-width: 44px;
  min-height: 44px;
  border: 1px solid var(--color-border);
  border-radius: 5px;
  padding: 7px 10px;
  background: var(--color-surface);
  color: var(--color-text);
  font: 700 14px ui-monospace, SFMono-Regular, Menlo, monospace;
  cursor: pointer;
  touch-action: manipulation;
}
.game-control--drop, .game-control--confirm { min-width: 76px; background: #1769aa; border-color: var(--color-accent); }
.game-control--rewind {
  min-width: 76px;
  border-color: #c084fc;
  background: #3b1d5c;
  color: #f5e9ff;
}
.game-control--rewind:hover:not(:disabled) { border-color: #e879f9; background: #55267a; }
.game-control:hover:not(:disabled) { border-color: var(--color-accent); background: var(--color-surface-alt); }
.game-control:disabled { opacity: .38; cursor: default; }
.game-control[hidden] { display: none; }
.game-control--attention:not(:disabled) {
  border-color: var(--color-accent);
  animation: game-control-attention 1s ease-in-out infinite;
}
.game-control--ready:not(:disabled) {
  border-color: #81e6b3;
  background: #147d64;
  animation: game-control-ready 1s ease-in-out infinite;
}
@keyframes game-control-attention {
  0%, 100% { box-shadow: 0 0 0 0 rgba(98, 176, 232, 0); }
  50% { box-shadow: 0 0 0 6px rgba(98, 176, 232, 0.35); }
}
@keyframes game-control-ready {
  0%, 100% { box-shadow: 0 0 0 0 rgba(129, 230, 179, 0); }
  50% { box-shadow: 0 0 0 6px rgba(129, 230, 179, 0.4); }
}
@media (prefers-reduced-motion: reduce) {
  .game-control--attention:not(:disabled) {
    animation: none;
    box-shadow: 0 0 0 2px rgba(98, 176, 232, 0.45);
  }
  .game-control--ready:not(:disabled) {
    animation: none;
    box-shadow: 0 0 0 2px rgba(129, 230, 179, 0.55);
  }
}
@media (max-width: 420px) {
  .game-controls { gap: 4px; width: calc(100vw - 12px); }
  .game-control { min-width: 40px; padding-inline: 7px; }
  .game-control--drop, .game-control--confirm { min-width: 68px; }
  .game-control--rewind { min-width: 68px; font-size: 12px; }
}
@media (hover: hover) and (pointer: fine) and (min-width: 721px) {
  :root { --game-controls-height: 0px; }
  .shell-region--bottom {
    min-height: calc(var(--app-footer-height) + env(safe-area-inset-bottom));
    padding-bottom: calc(var(--app-footer-height) + env(safe-area-inset-bottom));
  }
  .game-controls { display: none; }
  .game-controls[data-rewind-mode="true"] {
    position: fixed;
    top: max(16px, env(safe-area-inset-top));
    /* Stay aligned with the game canvas without competing with the HUD. */
    right: max(112px, calc((100vw - 680px) / 2 + 16px));
    z-index: 20;
    display: flex;
    width: auto;
    min-height: 0;
    padding: 0;
  }
  .game-controls[data-rewind-mode="true"] .game-control:not(.game-control--rewind) { display: none; }
}
/* The fixed, clipping viewport — sized to the available layout space and
   never itself transformed, so a zoom/pan can only move content within it,
   never move the clipping boundary itself and reveal empty page background
   past the board's edges. .zoom-layer (below) is what actually gets
   transformed. */
.game-stage {
  position: relative;
  display: grid;
  place-items: center;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
}
/* The Paradox rewind dialog (styles/overlays.css .rewind-panel) previews a
   live change to the board underneath it, so instead of overlaying the board
   (obscuring exactly the thing being previewed) it reserves its own footprint
   here: the board shrinks and re-centers to stay fully clear of the panel.
   RewindDialog measures the panel and sets both the class and the variable —
   see syncBoardClearance() in src/ui/rewind-dialog.ts. */
html.rewind-dialog-open .game-stage {
  padding-bottom: var(--rewind-dialog-clearance, 0px);
}
.zoom-layer {
  /* Establishes the containing block for the HUD's absolutely-positioned
     bands (styles/game-hud.css) — they must position relative to *this*
     element, not the outer .game-stage, or they'd stay fixed in place while
     the canvas zooms underneath them instead of moving together with it. */
  position: relative;
  width: 100%;
  height: 100%;
  min-width: 0;
  min-height: 0;
  display: grid;
  place-items: center;
}
canvas {
  display: block;
  flex: none;
  touch-action: none;
  cursor: pointer;
}
