/* Tessera — one stylesheet, no build step, no external requests. */

:root {
  color-scheme: light dark;

  --bg: #f6f7f9;
  --surface: #ffffff;
  --ink: #18202a;
  --ink-soft: #5b6673;
  --line: #d8dde4;
  --tile: #eceff3;
  --tile-line: #ccd3db;
  --blocked: #c3cad3;

  --exact: #3f9e6a;
  --present: #cba32f;
  --crossing: #4d7fc4;
  --absent: #8c96a3;

  --on-colour: #ffffff;
  --focus: #4d7fc4;

  --radius: 8px;
  --board-max: 22rem;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #11161d;
    --surface: #1a212a;
    --ink: #e9edf2;
    --ink-soft: #9aa5b3;
    --line: #2c3542;
    --tile: #222c38;
    --tile-line: #333e4c;
    --blocked: #0a0e13;

    --exact: #3f9e6a;
    --present: #b8902a;
    --crossing: #4a76b8;
    --absent: #3c4653;
  }
}

* {
  box-sizing: border-box;
}

/*
 * The UA rule for [hidden] is `display: none` at element specificity, so any
 * class here that sets `display` silently beats it — `.overlay { display: grid }`
 * left the help sheet painted over the board forever, while `overlay.hidden`
 * still read true in JS and the game accepted keystrokes underneath it.
 * Keep this above every display rule.
 */
[hidden] {
  display: none !important;
}

html,
body {
  margin: 0;
  height: 100%;
}

body {
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.5 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
    Helvetica, Arial, sans-serif;
  -webkit-text-size-adjust: 100%;
  overscroll-behavior: none;
}

/* ---------------------------------------------------------------- topbar */

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.5rem max(0.75rem, env(safe-area-inset-left));
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}

.wordmark {
  margin: 0;
  font-size: 1.35rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.icon-button {
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  border: 1px solid transparent;
  border-radius: 50%;
  background: none;
  color: var(--ink-soft);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}

.icon-button:hover {
  background: var(--tile);
  color: var(--ink);
}

.icon-button:focus-visible,
.key:focus-visible,
.selector:focus-visible,
.cell:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* ------------------------------------------------------------------- app */

.app {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
  width: 100%;
  max-width: 30rem;
  margin: 0 auto;
  padding: 0.75rem 0.75rem max(0.75rem, env(safe-area-inset-bottom));
}

.loading {
  margin: 3rem auto;
  color: var(--ink-soft);
}

.puzzle-line {
  margin: 0;
  color: var(--ink-soft);
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
}

.puzzle-line .dot {
  margin: 0 0.4rem;
  opacity: 0.5;
}

#guess-counter.low {
  color: var(--present);
  font-weight: 600;
}

/* Reads as a link, but it opens a dialog rather than navigating. */
.help-link {
  padding: 0;
  border: none;
  background: none;
  color: var(--focus);
  font: inherit;
  font-size: 0.85rem;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}

.help-link:hover {
  color: var(--ink);
}

.help-link:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: 3px;
}

/* ----------------------------------------------------------------- board */

.board-wrap {
  width: 100%;
  display: flex;
  justify-content: center;
}

/*
 * A narrow gutter for the line selectors, then one track per board column.
 * Keeping the selectors inside the same grid means they stay aligned with
 * their row or column at every width and every board size.
 *
 * --cells is set by the client from the board size; the value here is only a
 * fallback for the moment before the first render.
 */
.board {
  --cells: 7;
  display: grid;
  grid-template-columns: 1.15rem repeat(var(--cells), 1fr);
  grid-template-rows: 1.15rem repeat(var(--cells), 1fr);
  gap: 0.3rem;
  width: min(100%, var(--board-max));
  aspect-ratio: 1;
}

/* The 7x7 fits 40% more squares into the same width. */
.board[data-cells="7"] {
  gap: 0.2rem;
}

.cell {
  display: grid;
  place-items: center;
  position: relative;
  border: 1px solid var(--tile-line);
  border-radius: var(--radius);
  background: var(--tile);
  color: var(--ink);
  font-size: clamp(1.1rem, 7vw, 1.7rem);
  font-weight: 700;
  text-transform: uppercase;
  cursor: pointer;
  user-select: none;
  transition: background-color 120ms ease, border-color 120ms ease;
}

.board[data-cells="7"] .cell {
  font-size: clamp(0.7rem, 4.6vw, 1.15rem);
  border-radius: 5px;
}

/* Not a square you can play — it should read as a hole, not a dark tile. */
.cell.blocked {
  background: var(--blocked);
  border-color: transparent;
  border-radius: 3px;
  transform: scale(0.62);
  cursor: default;
}

.cell.revealed,
.cell.exact {
  background: var(--exact);
  border-color: var(--exact);
  color: var(--on-colour);
}

.cell.present {
  background: var(--present);
  border-color: var(--present);
  color: var(--on-colour);
}

.cell.crossing {
  background: var(--crossing);
  border-color: var(--crossing);
  color: var(--on-colour);
}

.cell.absent {
  background: var(--absent);
  border-color: var(--absent);
  color: var(--on-colour);
}

.cell .arrow {
  position: absolute;
  right: 3px;
  bottom: 1px;
  font-size: 0.6rem;
  font-style: normal;
  line-height: 1;
}

.cell.active {
  border-color: var(--focus);
  box-shadow: inset 0 0 0 1px var(--focus);
}

.cell.pending {
  color: var(--ink);
}

/* A revealed letter shown only as a hint under the cursor. */
.cell.ghost {
  color: var(--ink-soft);
  opacity: 0.55;
}

.cell.pop {
  animation: pop 110ms ease-out;
}

@keyframes pop {
  50% {
    transform: scale(1.07);
  }
}

.cell.flip {
  animation: flip 420ms ease-in-out both;
}

@keyframes flip {
  0% {
    transform: rotateX(0);
  }
  45% {
    transform: rotateX(90deg);
  }
  100% {
    transform: rotateX(0);
  }
}

.cell.shake {
  animation: shake 380ms ease-in-out;
}

@keyframes shake {
  25% {
    transform: translateX(-4px);
  }
  50% {
    transform: translateX(4px);
  }
  75% {
    transform: translateX(-2px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .cell.pop,
  .cell.flip,
  .cell.shake {
    animation: none;
  }
}

/* Line selectors -------------------------------------------------------- */

.selector {
  display: grid;
  place-items: center;
  padding: 0;
  border: none;
  border-radius: 4px;
  background: none;
  color: var(--ink-soft);
  font-size: 0.7rem;
  line-height: 1;
  cursor: pointer;
}

.selector:hover {
  color: var(--ink);
  background: var(--tile);
}

.selector.selected {
  color: var(--focus);
}

.selector.solved {
  color: var(--exact);
}

/* --------------------------------------------------------------- prompt */

.prompt {
  min-height: 1.5rem;
  margin: 0;
  text-align: center;
  font-size: 0.9rem;
  color: var(--ink-soft);
}

.prompt.error {
  color: #c25b4e;
  font-weight: 600;
}

.prompt.win {
  color: var(--exact);
  font-weight: 600;
}

/* -------------------------------------------------------------- history */

.history {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  width: 100%;
  max-height: 8.5rem;
  overflow-y: auto;
  padding-right: 0.2rem;
}

.entry {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.entry-label {
  flex: 0 0 4.4rem;
  text-align: right;
  white-space: nowrap;
}

.entry-tiles {
  display: flex;
  gap: 0.15rem;
}

.chip {
  position: relative;
  display: grid;
  place-items: center;
  width: 1.45rem;
  height: 1.45rem;
  border-radius: 4px;
  background: var(--absent);
  color: var(--on-colour);
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
}

/* Seven chips per row instead of five need to be smaller to fit a phone. */
body[data-cells="7"] .entry .chip {
  width: 1.2rem;
  height: 1.2rem;
  font-size: 0.62rem;
}

body[data-cells="7"] .entry-label {
  flex-basis: 4rem;
  font-size: 0.72rem;
}

.chip.exact {
  background: var(--exact);
}
.chip.present {
  background: var(--present);
}
.chip.crossing {
  background: var(--crossing);
}
.chip.absent {
  background: var(--absent);
}

.chip .arrow {
  position: absolute;
  right: 1px;
  bottom: 0;
  font-size: 0.55rem;
  font-style: normal;
  line-height: 1;
  opacity: 0.95;
}

/* ------------------------------------------------------------- keyboard */

.keyboard {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  width: 100%;
  margin-top: auto;
}

.krow {
  display: flex;
  justify-content: center;
  gap: 0.25rem;
}

.key {
  flex: 1 1 auto;
  min-width: 0;
  height: 3.1rem;
  border: none;
  border-radius: 5px;
  background: var(--tile);
  color: var(--ink);
  font-size: 0.9rem;
  font-weight: 600;
  text-transform: uppercase;
  cursor: pointer;
  touch-action: manipulation;
}

.key.wide {
  flex: 1.6 1 auto;
  font-size: 0.7rem;
}

.key.placed {
  background: var(--exact);
  color: var(--on-colour);
}
.key.present {
  background: var(--present);
  color: var(--on-colour);
}
.key.eliminated {
  background: var(--absent);
  color: var(--on-colour);
  opacity: 0.55;
}

/* -------------------------------------------------------------- overlay */

.overlay {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 1rem;
  background: rgb(0 0 0 / 0.55);
  z-index: 10;
}

.sheet {
  position: relative;
  width: min(100%, 30rem);
  max-height: 85vh;
  overflow-y: auto;
  padding: 1.25rem;
  border-radius: 12px;
  background: var(--surface);
}

.sheet h2 {
  margin: 0 0 0.75rem;
  font-size: 1.2rem;
}

.sheet h3 {
  margin: 1.25rem 0 0.4rem;
  font-size: 0.95rem;
}

.sheet p {
  margin: 0 0 0.6rem;
  font-size: 0.92rem;
}

.sheet-close {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  font-size: 1.4rem;
}

.legend {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}

.legend li {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  font-size: 0.9rem;
}

.legend .chip {
  flex: 0 0 auto;
}

/* Stats + result -------------------------------------------------------- */

.stats {
  display: flex;
  justify-content: space-around;
  margin: 0.5rem 0 1rem;
  text-align: center;
}

.stat-value {
  font-size: 1.6rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.stat-label {
  font-size: 0.72rem;
  color: var(--ink-soft);
}

.solution-down {
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.solution {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  margin: 0.75rem 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.95rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}

.button {
  display: block;
  width: 100%;
  margin-top: 0.75rem;
  padding: 0.75rem;
  border: none;
  border-radius: 8px;
  background: var(--exact);
  color: var(--on-colour);
  font-size: 0.95rem;
  font-weight: 700;
  cursor: pointer;
}

.button.secondary {
  background: var(--tile);
  color: var(--ink);
}

.countdown {
  margin-top: 0.75rem;
  text-align: center;
  font-size: 0.8rem;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}

@media (max-height: 700px) {
  :root {
    --board-max: 17rem;
  }
  .history {
    max-height: 4.5rem;
  }
  .key {
    height: 2.7rem;
  }
}
