/* Shared responsive, accessibility and board-surface rules for the generator
   and the player. Page CSS may override tokens but should not drop these. */

:root {
  --pm-focus: #0b5fff;
  --pm-ink: #1f1f1f;
  --pm-surface: #ffffff;
  --pm-muted: #5c5c5c;
  --pm-border: #b9b9b9;
  --pm-target: 2.25rem;
}

/* Always leave room for the vertical scrollbar, so that the generator and the player have the same width whether or
   not their page scrolls, and the layout does not jump when one switches between them. */
html {
  scrollbar-gutter: stable;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

/* The hidden attribute always wins over a display set by a class. */
[hidden] {
  display: none !important;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

:focus-visible {
  outline: 3px solid var(--pm-focus);
  outline-offset: 2px;
}

button,
select,
input,
summary,
.pm-btn {
  font: inherit;
}

.pm-btn,
button {
  min-height: var(--pm-target);
  min-width: var(--pm-target);
  padding: 0.25rem 0.75rem;
  color: var(--pm-ink);
  background: var(--pm-surface);
  border: 1px solid var(--pm-border);
  border-radius: 0.375rem;
  cursor: pointer;
}

.pm-btn:disabled,
button:disabled {
  color: var(--pm-muted);
  cursor: not-allowed;
}

.pm-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: var(--pm-target);
}

/* Touch and other coarse pointers get 44 x 44 CSS px targets. */
@media (pointer: coarse) {
  :root {
    --pm-target: 2.75rem;
  }

  .pm-btn,
  button,
  select,
  input[type="checkbox"],
  input[type="radio"],
  input[type="range"],
  summary,
  .pm-toggle,
  a.pm-btn {
    min-height: 44px;
    min-width: 44px;
  }

  input[type="checkbox"],
  input[type="radio"] {
    width: 44px;
    height: 44px;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
    transition-duration: 0.001ms !important;
  }
}

.pm-board {
  position: relative;
  width: 100%;
  height: 100%;
  min-width: 0;
  min-height: 0;
}

.pm-scroll {
  display: flex;
  width: 100%;
  height: 100%;
  overflow: auto;
  overscroll-behavior: contain;
  /* The page keeps scrolling outside the board; the board pans natively. */
  touch-action: pan-x pan-y;
}

.pm-board[data-mode="edit"] .pm-scroll {
  /* Painting must own the pointer; the editor pans with scrollbars and panTo. */
  touch-action: none;
}

.pm-board[data-mode="thumbnail"] .pm-scroll {
  overflow: hidden;
}

.pm-svg {
  display: block;
  flex: none;
  margin: auto;
  user-select: none;
  -webkit-user-select: none;
}

.pm-movable,
.pm-hit {
  touch-action: none;
}

.pm-movable {
  cursor: grab;
}

.pm-piece:focus {
  outline: none;
}

.pm-piece:focus-visible .pm-outline {
  stroke: var(--pm-focus);
  stroke-width: 0.18;
}

.pm-piece:focus-visible .pm-fill {
  filter: brightness(1.08);
}

.pm-preview {
  touch-action: none;
}

/* Toasts from core/browser/dom.js. */

.toast-host {
  position: fixed;
  right: 1rem;
  bottom: 1rem;
  z-index: 1000;
  display: grid;
  gap: 0.5rem;
  max-width: min(24rem, calc(100vw - 2rem));
}

.toast {
  padding: 0.625rem 0.875rem;
  color: #ffffff;
  background: #2b2b2b;
  border-radius: 0.375rem;
  box-shadow: 0 2px 8px rgb(0 0 0 / 30%);
  overflow-wrap: anywhere;
}

.toast-warning {
  color: #1f1f1f;
  background: #ffe08a;
}

.clipboard-buffer {
  position: fixed;
  left: -9999px;
  top: 0;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.app-footer {
  max-width: 100rem;
  margin-inline: auto;
  padding: 0.5rem 1rem 1rem;
  color: var(--gen-color-text-muted);
  font-size: 0.875rem;
  text-align: center;
}

.app-footer__inner {
  margin: 0;
}

.app-footer__copy::after {
  content: "\00b7";
  display: inline-block;
  margin-inline: 0.5rem;
}

.app-footer__link {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.15em;
}

.app-footer__link:hover {
  color: var(--gen-color-accent);
}

/* The dialogs of both apps (Share, Import, the code entry) open with a short fade and a slight rise over a soft blur. */
dialog.pm-pop[open] {
  animation: pm-pop 0.18s ease-out;
}

dialog.pm-pop::backdrop {
  background: rgb(10 14 28 / 52%);
  backdrop-filter: blur(3px);
}

@keyframes pm-pop {
  from {
    opacity: 0;
    transform: translateY(0.5rem) scale(0.98);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  dialog.pm-pop[open] {
    animation: none;
  }
}

/* The head of such a dialog: a tinted badge with an icon, the title with a muted line under it, and a close cross. */
.pm-head {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0 0 1rem;
}

.pm-head-badge {
  display: grid;
  flex: none;
  place-items: center;
  width: 2.625rem;
  height: 2.625rem;
  color: var(--gen-color-accent, var(--pm-focus));
  background: var(--gen-color-accent-soft, #dfe8ff);
  border-radius: 0.875rem;
}

.pm-head-badge svg {
  width: 1.4rem;
  height: 1.4rem;
  fill: none;
  stroke: currentcolor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.pm-head-titles {
  flex: 1 1 auto;
  min-width: 0;
}

.pm-head-title {
  margin: 0;
  font-size: 1.25rem;
  line-height: 1.2;
}

.pm-head-sub {
  margin: 0.125rem 0 0;
  overflow: hidden;
  color: var(--pm-muted);
  font-size: 0.875rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}

button.pm-head-x {
  display: grid;
  flex: none;
  place-items: center;
  align-self: flex-start;
  width: 2rem;
  min-width: 0;
  height: 2rem;
  min-height: 0;
  padding: 0;
  color: var(--pm-muted);
  background: transparent;
  border: 0;
  border-radius: 50%;
}

button.pm-head-x:hover:not(:disabled) {
  color: var(--pm-ink);
  background: var(--gen-color-hover, rgb(127 127 127 / 16%));
}

button.pm-head-x svg {
  width: 1.1rem;
  height: 1.1rem;
  fill: none;
  stroke: currentcolor;
  stroke-width: 2;
  stroke-linecap: round;
}

@media (pointer: coarse) {
  button.pm-head-x {
    width: var(--pm-target);
    height: var(--pm-target);
  }
}

.pm-head .pm-head-title {
  margin: 0;
  font-size: 1.25rem;
}

/* The puzzle code entry (the Player's, and the Generator's Import puzzle). */
.pm-dialog.pm-code {
  width: min(36rem, 94vw);
  max-height: calc(100vh - 2rem);
  max-height: calc(100dvh - 2rem);
  padding: 1.25rem 1.5rem;
  overflow-y: auto;
  border-radius: 1rem;
  box-shadow: 0 24px 64px rgb(10 14 28 / 38%);
}

.pm-code-label {
  display: block;
  margin: 0 0 0.375rem;
  color: var(--pm-muted);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.pm-code-field {
  display: block;
  width: 100%;
  min-height: 6.5rem;
  padding: 0.625rem 0.75rem;
  color: var(--pm-ink);
  font: 1rem/1.55 ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  letter-spacing: 0.04em;
  background: var(--gen-color-surface-2, #f1f1f1);
  border: 1px solid var(--gen-color-divider, var(--pm-border));
  border-radius: 0.75rem;
  overflow-wrap: anywhere;
  resize: vertical;
}

.pm-code-field:focus {
  border-color: var(--gen-color-accent, var(--pm-focus));
  outline: 2px solid var(--gen-color-accent-soft, #dfe8ff);
  outline-offset: 0;
}

/* An invalid code is marked by a heavier border as well as by the message under the field, not by colour alone. */
.pm-code-field[aria-invalid="true"] {
  border-color: var(--gen-color-danger);
  box-shadow: inset 0 0 0 1px var(--gen-color-danger);
}

.pm-code-note {
  margin: 0.375rem 0 0;
  font-size: 0.8125rem;
  color: var(--pm-muted);
}

.pm-code-problem {
  margin-top: 0.75rem;
  padding: 0.625rem 0.875rem;
  color: var(--gen-color-danger);
  background: var(--gen-color-danger-bg);
  border: 1px solid var(--gen-color-danger);
  border-inline-start-width: 4px;
  border-radius: 0.75rem;
}

.pm-code-problem p {
  margin: 0;
  overflow-wrap: anywhere;
}

.pm-code-problem .pm-code-candidate {
  margin-top: 0.375rem;
  color: var(--pm-ink);
}

.pm-code-offers {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.625rem;
}

.pm-code-busy {
  margin: 0.75rem 0 0;
  color: var(--pm-muted);
}

/* Open on the right, Cancel on its left. */
.pm-dialog.pm-code .pm-dialog-actions {
  flex-direction: row-reverse;
  justify-content: flex-start;
  margin-top: 1.25rem;
}

.pm-dialog.pm-code .pm-btn {
  min-height: 2.75rem;
  padding: 0.25rem 1rem;
  border-radius: 0.625rem;
}

.pm-dialog.pm-code .pm-btn.primary {
  font-weight: 600;
}

/* The Settings dialog of the narrow header: language and theme. It has no padding of its own, so that a click that
   lands on the dialog element is a click on its backdrop. */
.pm-settings-dialog {
  width: min(22rem, 92vw);
  padding: 0;
  color: var(--pm-ink);
  background: var(--pm-surface);
  border: 1px solid var(--pm-border);
  border-radius: 1rem;
  box-shadow: 0 24px 64px rgb(10 14 28 / 38%);
}

.pm-settings-box {
  padding: 1rem 1.25rem 0.75rem;
}

.pm-settings-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.75rem 0;
  border-top: 1px solid var(--gen-color-divider, var(--pm-border));
}

.pm-settings-label {
  font-weight: 600;
}

/* Narrow screens: the buttons and fields are smaller than the 44 px touch targets above, to leave room for the content.
   The pages' mobile layouts use the same breakpoint. */
@media (max-width: 767.98px) {
  :root {
    --pm-target: 2.25rem;
  }

  .pm-btn,
  button,
  select,
  input[type="range"],
  summary,
  .pm-toggle,
  a.pm-btn {
    min-height: 2.25rem;
    min-width: 2.25rem;
  }

  input[type="range"] {
    min-width: 0;
  }

  input[type="checkbox"],
  input[type="radio"] {
    width: 1.25rem;
    height: 1.25rem;
    min-width: 0;
    min-height: 0;
  }

  .pm-btn,
  button {
    padding: 0.125rem 0.625rem;
    font-size: 0.875rem;
  }

  .pm-dialog.pm-code .pm-btn {
    min-height: 2.25rem;
  }
}

/* The previous / next navigator of puzzles (puzzle-nav.js) is for the narrow layouts only. */
.puzzle-nav {
  display: none;
}

@media (max-width: 767.98px) {
  .puzzle-nav:not([hidden]) {
    display: grid;
    gap: 0.25rem;
    margin: 0 0 0.5rem;
  }

  .puzzle-nav__row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
  }

  .puzzle-nav__arrow {
    min-width: 2rem;
    min-height: 1.75rem;
    padding: 0 0.5rem;
    font-size: 0.75rem;
  }

  .puzzle-nav__position {
    min-width: 5.5rem;
    font-size: 0.875rem;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    text-align: center;
  }

  .puzzle-nav__actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.125rem;
  }

  .puzzle-nav__action {
    min-height: 1.5rem;
    padding: 0.125rem 0.5rem;
    color: var(--pm-muted);
    font-size: 0.75rem;
    background: transparent;
    border: 0;
  }
}
