/**
 * Playable board styling (Phase 8.2). Colors/font/radius/button classes come
 * from ../design/tokens.css (Phase 8.1) — this file only adds the layout and
 * board-specific rules tokens.css doesn't already cover.
 *
 * Phase 8.4 adds the difficulty tabs, puzzle-code/share UI, and print
 * support (the `.no-print` class + the `@media print` block at the bottom).
 *
 * Phase 8.5 adds the narrow-viewport breakpoint near the bottom (mobile),
 * the `.lang-toggle` button, and a visible focus ring for keyboard users —
 * see web/play/README.md for the rest of the a11y/i18n work, which is
 * mostly in index.html (ARIA attributes) and app.js (focus management,
 * i18n.js integration).
 */

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--gh-bg-cream);
  color: var(--gh-ink-primary);
  font-family: var(--gh-font-family);
  display: flex;
  justify-content: center;
  padding: 24px 16px 48px;
}

.app {
  position: relative;
  width: 100%;
  max-width: 480px;
}

.app-header {
  text-align: center;
  margin-bottom: 12px;
}

.app-header h1 {
  margin: 4px 0 0;
  font-size: 1.6rem;
}

/* Language toggle (Phase 8.5) — top-right corner of the page, out of the
   way of the centered header text. Positions relative to `.app`, not
   `.app-header`, so it stays anchored to the page corner even though it's
   the header's first child in source order (keeps it early in tab order). */
.lang-toggle {
  position: absolute;
  top: 0;
  right: 0;
  font-family: var(--gh-font-family);
  font-size: 0.75rem;
  font-weight: bold;
  padding: 4px 10px;
  border-radius: var(--gh-radius-button);
  border: 1px solid var(--gh-ink-primary);
  background: var(--gh-bg-off-white);
  color: var(--gh-ink-primary);
  cursor: pointer;
}

/* A visible focus ring for keyboard users everywhere on the page, including
   the board's roving-tabindex cells (a plain `<div tabindex>` has no default
   browser focus ring in every engine, so this can't be left to the
   platform default the way a real <button> could). */
:focus-visible {
  outline: 3px solid var(--gh-accent-rust);
  outline-offset: 1px;
}

/* Play aids (Phase 8.3) — timer, checking, hints, auto-candidates. */
.timer-chip {
  display: inline-block;
  margin-top: 8px;
  padding: 4px 12px;
  border-radius: var(--gh-radius-button);
  background: var(--gh-surface-sand);
  color: var(--gh-ink-primary);
  font-weight: bold;
  font-variant-numeric: tabular-nums;
  font-size: 0.9rem;
}

.solved-banner {
  text-align: center;
  font-weight: bold;
  color: var(--gh-ink-primary);
  background: var(--gh-surface-sage);
  border-radius: var(--gh-radius-button);
  padding: 8px 12px;
  margin: 0 0 8px;
}

.assisted-note {
  text-align: center;
  color: var(--gh-accent-rust);
  font-size: 0.8rem;
  margin: 0 0 8px;
}

.hint-panel {
  background: var(--gh-surface-sand);
  border: 1px solid var(--gh-border-tan-beige);
  border-radius: 10px;
  padding: 10px 14px;
  margin: 0 0 16px;
  font-size: 0.9rem;
}

.hint-panel p {
  margin: 0;
}

.aid-controls button {
  font-size: 0.85rem;
}

.err {
  color: var(--gh-accent-rust);
  font-size: 0.85rem;
  text-align: center;
  min-height: 1.2em;
  margin: 0 0 8px;
}

/* Difficulty picker (Phase 8.4) — same pill-tab pattern as GridHearth's own
   live play page (see web/design/BRAND.md). "Any" (data-difficulty="") is
   the default, unfiltered, weighted-random pick from Phase 7.2. */
.difficulty-tabs {
  display: flex;
  gap: 6px;
  justify-content: center;
  flex-wrap: wrap;
  margin: 0 0 14px;
}

.difficulty-tab {
  font-family: var(--gh-font-family);
  font-size: 0.85rem;
  font-weight: bold;
  padding: 6px 14px;
  border-radius: var(--gh-radius-button);
  border: 1px solid var(--gh-ink-primary);
  background: transparent;
  color: var(--gh-ink-primary);
  cursor: pointer;
}

.difficulty-tab[aria-selected="true"] {
  background: var(--gh-ink-primary);
  color: var(--gh-bg-off-white);
}

/* Puzzle code / share / load-by-code (Phase 8.4). */
.puzzle-meta {
  font-size: 0.85rem;
  text-align: center;
  margin: 0 0 16px;
}

.puzzle-code-row {
  margin: 0 0 8px;
}

.puzzle-code-row code {
  background: var(--gh-surface-sand);
  padding: 2px 6px;
  border-radius: 5px;
  font-size: 0.8rem;
}

.puzzle-code-row button {
  font-family: var(--gh-font-family);
  font-size: 0.8rem;
  padding: 5px 10px;
  cursor: pointer;
  margin-left: 4px;
}

.copy-confirm {
  color: var(--gh-ink-primary);
  font-weight: bold;
  margin-left: 6px;
}

.load-by-code label {
  display: block;
  color: var(--gh-border-teal-grey);
  margin-bottom: 4px;
}

.load-by-code-row {
  display: flex;
  gap: 6px;
  justify-content: center;
}

.load-by-code-row input {
  font: inherit;
  font-family: var(--gh-font-family);
  padding: 7px 10px;
  border: 1px solid var(--gh-border-teal-grey);
  border-radius: var(--gh-radius-button);
  background: var(--gh-bg-off-white);
  color: var(--gh-ink-primary);
  flex: 1;
  min-width: 0;
}

.load-by-code-row button {
  font-family: var(--gh-font-family);
  font-size: 0.85rem;
  padding: 7px 14px;
  cursor: pointer;
}

.board-wrap {
  margin: 0 auto 20px;
}

/* 9x9 board. Thin lines everywhere via border-teal-grey; a thicker
   ink-primary line every 3rd row/column marks the 3x3 boxes. Alternating
   box shading uses the sage surface color vs. the cream background — see
   web/design/BRAND.md's sudokuBoard note (visual match, not yet
   re-measured directly on the live play page). */
.grid {
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  aspect-ratio: 1;
  width: 100%;
  border: 2px solid var(--gh-ink-primary);
  border-radius: 6px;
  overflow: hidden;
}

.cell {
  position: relative;
  background: var(--gh-bg-cream);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: clamp(16px, 5.5vw, 28px);
  border: 1px solid var(--gh-border-teal-grey);
  cursor: pointer;
  user-select: none;
}

.cell.box-shaded {
  background: var(--gh-surface-sage);
}

.cell.r0, .cell.r3, .cell.r6 {
  border-top: 2px solid var(--gh-ink-primary);
}
.cell.c0, .cell.c3, .cell.c6 {
  border-left: 2px solid var(--gh-ink-primary);
}
.cell.r8 {
  border-bottom: 2px solid var(--gh-ink-primary);
}
.cell.c8 {
  border-right: 2px solid var(--gh-ink-primary);
}

.cell.given {
  font-weight: bold;
  cursor: default;
}

.cell.selected {
  background: var(--gh-accent-amber);
}

.cell.selected.box-shaded {
  /* Selection always wins over box shading, otherwise the amber highlight
     looks muddy mixed with sage. */
  background: var(--gh-accent-amber);
}

/* Phase 8.3 — Check marks a mismatch against the solution by coloring just
   the digit rust (the palette's only non-teal/amber accent), rather than a
   new color tokens.json doesn't define. */
.cell.incorrect .value {
  color: var(--gh-accent-rust);
}

.cell .value {
  line-height: 1;
}

.cell .notes {
  position: absolute;
  inset: 2px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  font-size: clamp(7px, 1.8vw, 10px);
  color: var(--gh-border-teal-grey);
  font-weight: normal;
  pointer-events: none;
}

.cell .notes span {
  display: flex;
  align-items: center;
  justify-content: center;
}

.controls {
  display: flex;
  flex-direction: column;
  gap: 14px;
  align-items: center;
}

.numpad {
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  gap: 6px;
  width: 100%;
}

.numpad-btn {
  font: inherit;
  font-family: var(--gh-font-family);
  font-weight: bold;
  padding: 10px 0;
  border-radius: var(--gh-radius-button);
  border: 1px solid var(--gh-ink-primary);
  background: var(--gh-bg-off-white);
  color: var(--gh-ink-primary);
  cursor: pointer;
}

.numpad-btn:active {
  background: var(--gh-surface-sand);
}

.edit-controls,
.aid-controls,
.puzzle-controls {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: center;
  width: 100%;
}

.edit-controls button,
.aid-controls button,
.puzzle-controls button {
  font-family: var(--gh-font-family);
  font-size: 0.9rem;
  padding: 9px 14px;
  cursor: pointer;
}

.edit-controls button[aria-pressed="true"] {
  background: var(--gh-ink-primary);
  color: var(--gh-bg-off-white);
}

.edit-controls button:disabled,
.aid-controls button:disabled,
.puzzle-controls button:disabled {
  opacity: 0.5;
  cursor: default;
}

/* Mobile / narrow-viewport (Phase 8.5). The layout above already flexes down
   to phone width via `max-width`, `clamp()` cell/note font sizes, and
   flex-wrap on the button rows, but a few things get genuinely cramped below
   ~420px (small phones in portrait): the numpad's 9 equal columns, the
   puzzle-code row's inline buttons, and the load-by-code input+button row.
   This breakpoint only tightens spacing/sizing — no layout is restructured,
   so nothing here should be needed above it. */
@media (max-width: 420px) {
  body {
    padding: 16px 8px 40px;
  }

  .numpad {
    gap: 4px;
  }

  .numpad-btn {
    padding: 8px 0;
    font-size: 0.95rem;
  }

  .edit-controls button,
  .aid-controls button,
  .puzzle-controls button {
    font-size: 0.8rem;
    padding: 8px 10px;
  }

  .puzzle-code-row button {
    display: block;
    margin: 6px auto 0;
  }

  .load-by-code-row {
    flex-direction: column;
  }

  .load-by-code-row input {
    width: 100%;
  }

  .lang-toggle {
    font-size: 0.7rem;
    padding: 3px 8px;
  }
}

/* Print (Phase 8.4) — a plain "Print" button calling window.print(). Hide
   every interactive control (`.no-print`, applied in index.html) and print
   just the heading and grid: no amber selection highlight (meaningless on
   paper, and it wouldn't photocopy legibly), no sage box shading (saves
   ink; the thicker box-boundary lines already make the 3x3 blocks clear on
   paper), full black-on-white contrast instead of the brand palette. */
@media print {
  .no-print {
    display: none !important;
  }

  body {
    background: #fff;
    padding: 0;
    display: block;
  }

  .app {
    max-width: none;
  }

  .cell,
  .cell.box-shaded,
  .cell.selected,
  .cell.selected.box-shaded {
    background: #fff;
  }

  .cell,
  .grid {
    border-color: #000;
  }

  .cell .value,
  .app-header h1,
  .gh-eyebrow-label {
    color: #000;
  }

  .cell.incorrect .value {
    color: #000;
  }
}
