/* Board mount / hydration loading — puzzle-page-shell only. */

html.is-play body #playMain.puzzle-page-shell .board-wrap > .board-loading {
  grid-area: 1 / 1;
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  box-sizing: border-box;
  width: 100%;
  min-height: min(100vw - 48px, var(--play-board-max, 720px));
  max-width: min(100%, var(--play-board-max, 720px));
  margin-inline: auto;
  padding: 20px 16px;
  text-align: center;
  color: var(--ink, #2b2419);
  pointer-events: auto;
}

html.is-play body #playMain.puzzle-page-shell .board-wrap > .board-loading[hidden] {
  display: none !important;
}

html.is-play body #playMain.puzzle-page-shell .board-wrap.is-board-loading {
  min-height: min(100vw - 48px, var(--play-board-max, 720px));
}

html.is-play body.ds-codebreaker #playMain.puzzle-page-shell .board-wrap.is-board-loading,
html.is-play body #playMain.puzzle-page-shell .board-wrap.is-board-loading:has(.cb-board) {
  aspect-ratio: auto;
  min-height: max(220px, min(70vw, 24rem));
}

html.is-play body #playMain.puzzle-page-shell .board-wrap.is-board-loading > :is(#board, .board, .cb-board) {
  /* Keep SSR nodes in DOM for hydration; loading supplies visible stage height. */
  visibility: hidden;
  pointer-events: none;
}

html.is-play body #playMain.puzzle-page-shell .board-wrap.is-board-ready > .board-loading {
  display: none !important;
}

/* Undo the unresolved 1px clip only after the gate has released the stage.
   Digit color stays on the design-system given/entry/error rules. */
html.is-play:not(.is-play-gated):not(.is-start-unresolved):not(.is-play-board-obscured) body #playMain.puzzle-page-shell .board-wrap.is-board-ready > :is(#board, .board, .cb-board) {
  position: relative;
  width: min(100%, var(--play-board-max, 720px));
  height: auto;
  max-height: none;
  margin-inline: auto;
  overflow: visible;
  clip: auto;
  clip-path: none;
  white-space: normal;
  visibility: visible;
  pointer-events: auto;
}

.board-loading-text {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1.35;
}

.board-loading-spinner {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 3px solid color-mix(in srgb, var(--ink, #2b2419) 18%, transparent);
  border-top-color: var(--cta, #c45c26);
  box-sizing: border-box;
}

@media (prefers-reduced-motion: no-preference) {
  .board-loading-spinner {
    animation: board-loading-spin 0.9s linear infinite;
  }
}

@keyframes board-loading-spin {
  to {
    transform: rotate(360deg);
  }
}

.board-loading.is-failed .board-loading-spinner {
  display: none;
}

.board-loading-error {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.4;
  color: var(--danger, #8b2e2e);
}

.board-loading-actions {
  display: flex;
  justify-content: center;
  gap: 8px;
}

.board-loading-actions button {
  min-height: 44px;
  min-width: 8rem;
}

/* Session resolve pending: the shared loader is the status, not the 10px dot
   or an empty start card stacked on top of it. */
html.is-play.is-start-unresolved body #playMain.puzzle-page-shell .board-wrap > #startGate.start-gate.is-pending:not(.is-already-played) {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  pointer-events: none;
}

html.is-start-unresolved #startGate.is-pending .start-pending {
  display: none !important;
}

/* Start / unlock / replay gate visible: loading stays hidden (owned by start-game-dialog). */
html.is-play-gated body #playMain.puzzle-page-shell .board-wrap > .board-loading:not(.is-failed) {
  display: none !important;
}

html.is-play-board-obscured body #playMain.puzzle-page-shell .board-wrap > .board-loading {
  display: none !important;
}
