/* JIGSAW3D SPECIFIC STYLING
   The play area frame (body.game-3d-wrapper .game-canvas-container) is shared
   by every 3D game and lives in css/index3D/unified-3d-game.css under
   "FRAMED PLAY STAGE". This sheet adds the jigsaw table's studio backdrop,
   its loading card and the sound toggle.
*/

canvas {
  display: block;
  width: 100%;
  height: 100%;
  cursor: grab;
}

canvas:active {
  cursor: grabbing;
}

/* ============================================================================
   STUDIO BACKDROP
   The WebGL canvas is transparent; this gradient is the environment the
   3D table sits in — the word scramble stage's colours (violet air over a
   subtly lit table; pale paper in light) as a soft overhead spotlight so
   the board reads as lit product photography. Overrides the shared flat
   paper mat (later in the cascade + higher specificity).
   ============================================================================ */

body.game-3d-wrapper .game-canvas-container {
  background:
    radial-gradient(115% 90% at 50% 0%, #241f2e 0%, #1a1723 48%, #14121a 100%);
}

html[data-theme='dark'] body.game-3d-wrapper .game-canvas-container {
  background:
    radial-gradient(115% 90% at 50% 0%, #241f2e 0%, #1a1723 48%, #14121a 100%);
}

html[data-theme='light'] body.game-3d-wrapper .game-canvas-container {
  background:
    radial-gradient(115% 90% at 50% 0%, #f0eade 0%, #e6dfd3 55%, #d9cfbf 100%);
}

/* ============================================================================
   STAGE FLOOR EXTENT
   The shared .ws3d-grid-floor band (unified-3d-game.css) sets its horizon at
   46% of the stage, and the perspective plane's near edge lands mid-stage at
   this aspect — the page background showed above the horizon AND below the
   plane's trailing edge. Jigsaw's table instead runs from a horizon about a
   quarter of the way down (backdrop sky above it, as on the WebGL-floored
   games) all the way to the bottom of the frame: the plane is deep enough
   that its foreshortened near edge projects past the stage bottom.
   ============================================================================ */

#canvas-container .ws3d-grid-floor {
  top: 24%;
}

#canvas-container .ws3d-grid-floor::before {
  /* Override the inset-derived height: without the extra depth the rotated
     plane's near edge stops mid-air. 135% clears the bottom at desktop and
     phone stage aspects while staying well under the perspective distance
     (900px / sin 55° ≈ 1099px of depth), where the projection would invert. */
  bottom: auto;
  height: 135%;
}

/* ============================================================================
   STAGE FLOOR DEPTH
   The shared rule fills this plane with one flat colour: its far-edge haze
   layer is painted in that same colour, so it cancels out and the horizon and
   the near edge render identically. On the extended plane above that made the
   floor read as a card the board sits on rather than a surface running away
   from the viewer beneath it.

   These rules lay a ramp over the plane instead: transparent on the
   horizon, where the surface colour is already the floor, lifting to the lit
   surface colour at the near edge, so the floor darkens with distance like the
   fogged floors of the WebGL-based games. The ramp sits above the grid layers,
   so the lines also soften with distance instead of staying equally sharp the
   whole way down. Foreshortening keeps the plane's near edge several hundred
   pixels below the stage bottom (see above), so only the ramp's first three
   quarters are ever on screen.

   One ramp per theme, each over that theme's own grid line colour.
   ============================================================================ */

#canvas-container .ws3d-grid-floor::before {
  background-image:
    linear-gradient(180deg, rgba(88, 82, 96, 0) 0%, rgba(88, 82, 96, 1) 100%),
    repeating-linear-gradient(0deg, rgba(111, 103, 143, 0.75) 0 2px, transparent 2px 64px),
    repeating-linear-gradient(90deg, rgba(111, 103, 143, 0.75) 0 2px, transparent 2px 64px);
}

html[data-theme='light'] #canvas-container .ws3d-grid-floor::before {
  background-image:
    linear-gradient(180deg, rgba(137, 133, 134, 0) 0%, rgba(137, 133, 134, 1) 100%),
    repeating-linear-gradient(0deg, rgba(167, 158, 192, 0.7) 0 2px, transparent 2px 64px),
    repeating-linear-gradient(90deg, rgba(167, 158, 192, 0.7) 0 2px, transparent 2px 64px);
}

/* ============================================================================
   SOUND TOGGLE — small stage HUD button, every viewport
   ============================================================================ */

.sound-toggle {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 60;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--news-paper);
  border: 2px solid var(--news-ink);
  color: var(--news-ink);
  font-size: 1.05rem;
  line-height: 1;
  cursor: pointer;
  box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.22);
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.15s ease, background 0.15s ease;
}

.sound-toggle:hover {
  transform: scale(1.06);
}

.sound-toggle:active {
  transform: scale(0.92);
  background: var(--news-accent);
  border-color: var(--news-accent);
}

.header-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  padding: var(--spacing-lg);
  background: linear-gradient(to bottom, var(--news-paper) 0%, transparent 100%);
  z-index: 50;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  pointer-events: none;
}

.header-overlay > * {
  pointer-events: auto;
}

.header-left,
.header-right {
  display: flex;
  gap: var(--spacing-md);
  align-items: center;
}

.header-title {
  font-family: var(--news-font-display);
  font-size: 1.5rem;
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-text-primary);
}

.header-subtitle {
  font-size: 0.875rem;
  color: var(--color-text-secondary);
}

.control-panel {
  position: absolute;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--news-paper);
  border: 1px solid var(--news-rule-light);
  border-radius: 0;
  padding: var(--spacing-lg);
  z-index: 50;
  box-shadow: var(--shadow-hard-lg);
  display: flex;
  gap: var(--spacing-md);
  flex-wrap: wrap;
  justify-content: center;
  max-width: 90vw;
}

.control-panel button {
  padding: var(--spacing-sm) var(--spacing-md);
  background: var(--news-btn-bg);
  color: var(--color-text-primary);
  border: 1.5px solid var(--news-rule);
  border-radius: 0;
  cursor: pointer;
  font-family: inherit;
  font-weight: 600;
  font-size: var(--font-size-sm);
  box-shadow: 1px 1px 0 rgba(0, 0, 0, 0.10);
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.control-panel button:hover {
  background: var(--news-btn-bg-hover);
  color: var(--news-paper);
  border-color: var(--news-accent);
}

.score-display {
  position: absolute;
  top: 70px;
  left: 20px;
  background: var(--news-paper);
  border: 1px solid var(--news-rule-light);
  padding: var(--spacing-md) var(--spacing-lg);
  border-radius: 0;
  z-index: 50;
  box-shadow: var(--shadow-hard);
}

.score-label {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  text-transform: uppercase;
}

.score-value {
  font-size: 1.5rem;
  font-weight: bold;
  color: var(--color-text-primary);
}

.progress-indicator {
  position: absolute;
  top: 70px;
  right: 20px;
  background: var(--news-paper);
  border: 1px solid var(--news-rule-light);
  padding: var(--spacing-md) var(--spacing-lg);
  border-radius: 0;
  z-index: 50;
  min-width: 200px;
  box-shadow: var(--shadow-hard);
}

.progress-label {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  text-transform: uppercase;
  margin-bottom: var(--spacing-sm);
}

.progress-bar {
  width: 100%;
  height: 8px;
  background: var(--news-rule-light);
  border-radius: 0;
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  background: var(--news-ink);
  transition: width 0.3s ease-out;
}

.progress-percent {
  margin-top: var(--spacing-sm);
  text-align: center;
  font-size: var(--font-size-sm);
  color: var(--color-text-primary);
  font-weight: 600;
}

/* Loading card: framed like the site's other newspaper surfaces, floating
   over the studio backdrop while texture + pieces prepare. */
#loading {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 100;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--spacing-lg);
  padding: 30px 46px;
  background: var(--news-paper);
  border: 3px double var(--news-ink);
  box-shadow: var(--shadow-hard-lg);
  color: var(--color-text-primary);
  text-align: center;
  pointer-events: none;
}

.loading-spinner {
  width: 44px;
  height: 44px;
  border: 3px solid var(--news-rule-light);
  border-top: 3px solid var(--news-accent);
  border-radius: var(--radius-full);
  animation: spin 0.9s cubic-bezier(0.55, 0.15, 0.45, 0.85) infinite;
}

.loading-text {
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-text-secondary);
}

@media (max-width: 768px) {
  .header-overlay {
    flex-direction: column;
    gap: var(--spacing-md);
  }

  .control-panel {
    bottom: 10px;
    left: 10px;
    right: 10px;
    transform: none;
    max-width: none;
  }

  .score-display,
  .progress-indicator {
    top: 70px;
    position: relative;
    margin: var(--spacing-md);
  }
}

.hidden {
  display: none !important;
}

.piece-move-panel {
  display: grid;
  grid-template-columns: 60px 60px 60px;
  grid-template-rows: 44px 44px 44px;
  gap: var(--spacing-xs);
  justify-content: center;
  -webkit-user-select: none;
  user-select: none;
}

.piece-move-panel.is-disabled {
  opacity: 0.45;
  pointer-events: none;
}

.piece-move-btn,
.piece-move-label {
  width: 60px;
  height: 44px;
  border-radius: 0;
  background: var(--news-btn-bg);
  border: 1px solid var(--news-rule);
  color: var(--color-text-primary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.875rem;
  font-weight: 600;
}

.piece-move-btn {
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.piece-move-btn:hover {
  background: var(--news-btn-bg-hover);
  color: var(--news-paper);
  border-color: var(--news-accent);
}

.piece-move-label {
  background: var(--color-tile-bg);
  border: 1px solid var(--news-rule-light);
  font-weight: 700;
}

.piece-rotation-panel {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-xs);
  -webkit-user-select: none;
  user-select: none;
}

.jigsaw-piece-rotation-panel {
  margin-top: var(--spacing-sm);
}

.piece-rotation-panel.is-disabled {
  opacity: 0.45;
  pointer-events: none;
}

.rotation-title {
  font-size: 0.75rem;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 700;
}

.rotation-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: var(--spacing-xs);
}

.rotation-btn {
  height: 44px;
  border-radius: 0;
  border: 1.5px solid var(--news-ink);
  cursor: pointer;
  box-shadow: 1px 1px 0 rgba(0, 0, 0, 0.10);
  transition: filter 0.15s;
}

.rotation-btn:hover {
  filter: brightness(1.08);
}

/* Axis colours drawn from the shared palette (accent / correct / warn) so the
   X/Y/Z controls stay distinguishable without leaving the newspaper scheme. */
.rotation-btn.rotation-x {
  background: var(--news-accent);
}

.rotation-btn.rotation-y {
  background: var(--news-correct);
}

.rotation-btn.rotation-z {
  background: var(--news-warn);
}

.difficulty-selector {
  display: flex;
  gap: var(--spacing-xs);
  padding: var(--spacing-xs);
}

.difficulty-btn {
  flex: 1;
  padding: var(--spacing-xs) var(--spacing-sm);
  border: 1px solid var(--news-rule);
  border-radius: 0;
  background: transparent;
  color: var(--color-text-secondary);
  font-size: 0.8rem;
  font-family: inherit;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.15s;
}

.difficulty-btn.active {
  background: var(--news-ink);
  border-color: var(--news-ink);
  color: var(--news-paper);
}

.difficulty-btn:hover:not(.active) {
  border-color: var(--news-ink);
  color: var(--color-text-primary);
}

.lock-toggle {
  width: 100%;
  justify-content: flex-start;
}

.lock-toggle.active {
  background: var(--news-ink);
  border-color: var(--news-ink);
}

.lock-icon {
  font-size: 1rem;
  margin-right: var(--spacing-xs);
}

.lock-text {
  font-weight: 500;
}

.progress-bar {
  height: 8px;
  background: var(--news-rule-light);
  border-radius: 0;
  overflow: hidden;
}

.jigsaw-progress-bar {
  margin-top: var(--spacing-sm);
}

.progress-fill {
  height: 100%;
  background: var(--news-ink);
  border-radius: 0;
  transition: width 0.3s;
  width: 0%;
}

#puzzle-timer {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--color-text-primary);
  background: var(--news-paper);
  padding: 0.35rem 0.6rem;
  border-radius: 0;
  border: 1px solid var(--news-rule-light);
}

.jigsaw-timer-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: var(--spacing-sm);
}

.jigsaw-inline-actions {
  display: flex;
  gap: var(--spacing-xs);
}

.jigsaw-inline-action-btn {
  flex: 1;
}

.help-modal {
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  padding: var(--spacing-lg);
  background: rgba(0, 0, 0, 0.8);
}

.help-content {
  background: var(--news-paper);
  border-radius: 0;
  padding: var(--spacing-xl);
  max-width: 600px;
  width: 90%;
  max-height: 80vh;
  overflow-y: auto;
  box-shadow: var(--shadow-hard-lg);
  border: 3px double var(--news-ink);
  position: relative;
}

.help-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--spacing-lg);
}

.help-title {
  font-family: var(--news-font-display);
  font-size: 1.5rem;
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-text-primary);
}

.help-close {
  background: var(--news-btn-bg);
  border: 1px solid var(--news-rule);
  color: var(--color-text-secondary);
  font-size: 1.5rem;
  cursor: pointer;
  padding: var(--spacing-xs) var(--spacing-sm);
  border-radius: 0;
  line-height: 1;
  transition: all var(--transition-base);
}

.help-close:hover {
  background: var(--news-btn-bg-hover);
  color: var(--news-paper);
  border-color: var(--news-accent);
}

.help-section {
  margin-bottom: var(--spacing-lg);
}

.help-section h3 {
  font-size: 1rem;
  font-weight: 600;
  margin-bottom: var(--spacing-sm);
  display: flex;
  align-items: center;
  gap: var(--spacing-xs);
}

.help-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--spacing-xs);
}

.help-list li {
  display: flex;
  align-items: flex-start;
  gap: var(--spacing-sm);
  color: var(--color-text-secondary);
  font-size: 0.8rem;
  line-height: 1.5;
}

.help-key {
  background: var(--news-btn-bg);
  padding: 2px 8px;
  border-radius: 0;
  font-family: var(--font-family-mono);
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--color-text-primary);
  border: 1px solid var(--news-rule);
  min-width: 70px;
  text-align: center;
}

.completion-message {
  z-index: var(--z-modal-backdrop, 10020);
}

.completion-message.show {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

.completion-inner {
  position: relative;
  background: var(--news-paper);
  border-radius: 0;
  padding: var(--spacing-xl);
  text-align: center;
  max-width: 500px;
  width: 90%;
  box-shadow: var(--shadow-hard-lg);
  border: 3px double var(--news-ink);
}

.completion-icon {
  font-size: 4rem;
  margin-bottom: var(--spacing-md);
}

.completion-title {
  font-family: var(--news-font-display);
  font-size: 2rem;
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-text-primary);
  margin-bottom: var(--spacing-sm);
}

.completion-subtitle {
  font-size: 1rem;
  color: var(--color-text-secondary);
  margin-bottom: var(--spacing-lg);
}

.completion-stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--spacing-md);
  margin-bottom: var(--spacing-lg);
}

.completion-actions {
  display: flex;
  gap: var(--spacing-md);
  justify-content: center;
}

.completion-attribution {
  margin: 0 0 var(--spacing-lg);
  font-size: 0.85rem;
  font-style: italic;
  line-height: 1.4;
  color: var(--color-text-secondary);
  opacity: 0.85;
  max-width: 90%;
  margin-left: auto;
  margin-right: auto;
}

.stat-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.stat-label {
  font-size: 0.75rem;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.stat-value {
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--color-text-primary);
}
