/* Page shell for the in-browser player.
 *
 * The table itself — tiles, the two boards, the status band, the log, the inline
 * scoring panels and the tile flights — lives in ui/board.css, which is a copy of
 * web/play/ui/board.css (see web/play/ui/PORTING.md). The hosted player and the
 * local GUI therefore draw the *same* table from two different back ends: a Flask
 * server there, a Web Worker running ONNX in the tab here.
 *
 * This file is only what belongs to *this* page: the linen ground, the header and
 * its setup bar, the engine (model download) strip, the column layout, the supply
 * and "how this works" boxes, and a harder look at small screens — this one is
 * meant to be playable on a phone.
 *
 * Layout, top to bottom: header · engine strip · status band · the playfield
 * (the factories on the left, the two identical boards — you above, AI below —
 * beside them; <body data-boards="stack">, the + in settings, restores the big
 * boards under the factories) · inline scoring · the move log and the about
 * box · the bottom bar (the AI's clock and the tile totals). Nothing is ever
 * covered by anything: there is no overlay and no toast on this page.
 */

@import url("../ui/board.css");

* { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100vh;
  color: var(--ink);
  font: 15px/1.5 var(--font-body);
  background-color: var(--linen);
  /* woven linen: two hairline threads plus a warm vignette */
  background-image:
    linear-gradient(var(--linen-thread) 1px, rgba(0, 0, 0, 0) 1px),
    linear-gradient(90deg, var(--linen-thread) 1px, rgba(0, 0, 0, 0) 1px),
    radial-gradient(120% 90% at 50% 0%, var(--linen-warm) 0%, var(--linen) 55%, var(--linen-dark) 100%);
  background-size: 7px 7px, 7px 7px, 100% 100%;
}

h1, h2, h3 { margin: 0; font-weight: 400; }
button, input, select { font: inherit; color: inherit; }

/* ------------------------------------------------------------------ top bar */
.topbar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 14px 24px;
  padding: 12px clamp(14px, 3vw, 34px);
  background: linear-gradient(var(--topbar-top), var(--topbar-bottom));
  border-bottom: 1px solid var(--grout);
  box-shadow: 0 6px 18px -14px rgba(60, 44, 20, .6);
}
.brand { display: flex; align-items: baseline; gap: 12px; margin-right: auto; }
.brand-name {
  font-family: var(--font-display);
  font-size: 28px;
  letter-spacing: .16em;
  text-transform: uppercase;
  /* the title is glazed like a tile: cobalt with a highlight along the top */
  background: linear-gradient(var(--c0-hi), var(--c0) 55%, var(--c0-lo));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.brand-sub { font-family: var(--font-label); font-size: 12.5px; letter-spacing: .08em; color: var(--ink-soft); }

.setup { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px 14px; }
.field { display: flex; flex-direction: column; gap: 4px; }
.field-label {
  font-family: var(--font-label);
  font-size: 11px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.field select, .field input {
  padding: 6px 9px;
  min-width: 132px;
  background: var(--field-bg);
  border: 1px solid var(--grout);
  border-radius: 2px;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .8) inset;
}
.field-narrow input { min-width: 78px; width: 88px; }
.field-narrow select { min-width: 132px; }
/* the opponent's glaze, as a small tile beside the menu and on its board */
.bot-pick { display: flex; align-items: center; gap: 7px; }
.bot-pick select { min-width: 150px; }
.bot-chip {
  width: 14px;
  height: 14px;
  border-radius: 3px;
  flex: none;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .35), 0 1px 0 rgba(255, 255, 255, .45) inset;
}
.check { display: flex; align-items: center; gap: 7px; padding-bottom: 6px; font-size: 14px; }
.check.coach { padding: 5px 10px 5px 8px; border: 1px solid var(--grout); border-radius: 2px; background: var(--field-bg); }
.check.coach.off { opacity: .55; }

.btn {
  padding: 7px 15px;
  border: 1px solid var(--grout);
  border-radius: 2px;
  background: linear-gradient(var(--btn-top), var(--btn-bottom));
  cursor: pointer;
  font-family: var(--font-label);
  font-size: 13px;
  letter-spacing: .1em;
  text-transform: uppercase;
  transition: transform .12s ease, box-shadow .12s ease, background .12s ease;
}
.btn:hover { background: linear-gradient(var(--btn-top-hover), var(--btn-bottom-hover)); }
.btn:active { transform: translateY(1px); }
.btn-primary {
  color: var(--btn-primary-ink);
  border-color: var(--c0-lo);
  background: linear-gradient(var(--btn-primary-top), var(--c0) 60%, var(--btn-primary-bottom));
  box-shadow: 0 1px 0 rgba(255, 255, 255, .35) inset, 0 2px 6px -3px rgba(20, 40, 80, .8);
}
.btn-primary:hover { background: linear-gradient(var(--btn-primary-top-hover), var(--btn-primary-bottom-hover)); }
.btn:disabled { opacity: .45; cursor: not-allowed; transform: none; }

:where(a, button, input, select, [tabindex]):focus-visible {
  outline: 2px solid var(--c4-lo);
  outline-offset: 2px;
}

/* ------------------------------------------------------- engine status bar */
/* The net is a 13 MB download, so its state is not a detail to hide in a corner:
 * it gets its own strip under the header, and the Deal button stays disabled
 * until the worker says it is ready. */
.engine-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  padding: 8px clamp(14px, 3vw, 34px);
  background: linear-gradient(var(--engine-top), var(--engine-bottom));
  border-bottom: 1px solid var(--grout);
  font-family: var(--font-label);
  font-size: 12px;
  letter-spacing: .06em;
  color: var(--ink-soft);
}
.engine-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--c1);
  box-shadow: 0 0 0 3px var(--c1-wash);
  animation: kiln 1.2s ease-in-out infinite;
}
@keyframes kiln {
  0%, 100% { opacity: .35; }
  50% { opacity: 1; }
}
.engine-bar.ready .engine-dot { background: var(--c4); box-shadow: 0 0 0 3px var(--c4-wash); animation: none; }
.engine-bar.failed .engine-dot { background: var(--c2); box-shadow: 0 0 0 3px var(--c2-wash); animation: none; }
.engine-text { flex: 1 1 auto; min-width: 200px; }

/* what's new: one dismissible line, edged in cobalt so it reads as news */
.news-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px clamp(14px, 3vw, 34px);
  background: linear-gradient(var(--plaster-hi), var(--plaster));
  border-bottom: 1px solid var(--grout);
  border-left: 4px solid var(--c0);
  font-family: var(--font-label);
  font-size: 13px;
  letter-spacing: .03em;
  color: var(--ink);
}
.news-badge {
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--c0);
  color: var(--plaster-hi);
  font-size: 10.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  white-space: nowrap;
}
.news-bar[hidden] { display: none; }
.news-text { flex: 1 1 auto; }
.news-line { display: block; line-height: 1.55; }
.news-close {
  border: 1px solid var(--badge-edge);
  background: none;
  border-radius: 999px;
  width: 22px;
  height: 22px;
  line-height: 1;
  cursor: pointer;
  color: var(--ink-soft);
}
.news-close:hover { color: var(--ink); }
.engine-badge {
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--badge-bg);
  border: 1px solid var(--badge-edge);
  text-transform: uppercase;
  letter-spacing: .12em;
  font-size: 11px;
  color: var(--c0-ink);
  white-space: nowrap;
}

/* -------------------------------------------------------------------- table */
.table {
  display: flex;
  flex-direction: column;
  gap: clamp(10px, 1.4vw, 18px);
  padding: clamp(12px, 1.8vw, 22px) clamp(12px, 3vw, 34px) 44px;
  max-width: 1560px;
  margin: 0 auto;
}

.middle-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-top: 10px;
}

/* The playfield. Two ways to draw it, picked in the settings panel and
 * defaulted per device (see ui/layout.js):
 *   stack (the +, a desktop's default) — the classic table: big boards, side
 *     by side below the factories;
 *   side (the −, a phone's default) — the whole game on one screen: the
 *     factories on the left, both boards, smaller, stacked beside them.
 * The base rules below are the stack look, so a desktop paints correctly
 * before any script runs; the phone media query flips its own default. */
.playfield {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(10px, 1.4vw, 18px);
  align-items: start;
}
.boards {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(10px, 1.4vw, 18px);
  align-items: start;
}

body[data-boards="side"] .playfield {
  grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
}
body[data-boards="side"] .boards {
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(8px, 1vw, 14px);
}
/* side layout: both boards must fit beside the factories, so they shrink */
body[data-boards="side"] .board { --tile: clamp(13px, 2.1vw, 36px); }

.below {
  display: grid;
  grid-template-columns: minmax(0, 1.7fr) minmax(240px, .8fr);
  gap: clamp(10px, 1.4vw, 18px);
  align-items: start;
}
.below-side { display: flex; flex-direction: column; gap: clamp(10px, 1.4vw, 18px); }

/* ------------------------------------------------------------- game record */
/* Shown only once a game is over: the finished game, offered as a file. Quiet
 * by construction, because it is an invitation and not a demand. */
.record-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 18px;
}
.record-bar[hidden] { display: none; }
.record-note {
  flex: 1 1 320px;
  margin: 0;
  font-size: 13.5px;
  color: var(--ink-soft);
}
.record-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.record-link {
  font-family: var(--font-label);
  font-size: 12px;
  letter-spacing: .06em;
  color: var(--c0);
}
.record-bar.done .record-note { color: var(--ink); }

/* --------------------------------------------------------------- bottom bar */
/* The quiet end of the page: the AI's clock lives here (moved off the top bar,
 * where it crowded a phone), next to one line of totals. #lid-row inside the
 * totals is where discarded tiles fly — a target, so it keeps a real box. */
.bottom-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 12px 22px;
}
.counts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 16px;
  padding-bottom: 8px;
  font-family: var(--font-label);
  font-size: 12px;
  letter-spacing: .06em;
  color: var(--ink-soft);
}
#lid-row { border-radius: 3px; padding: 2px 4px; transition: background .3s ease; }
#lid-row.receiving { background: var(--lid-receiving); }

/* --------------------------------------------------------------- about box */
.about p { margin: 0 0 8px; font-size: 13.5px; color: var(--ink-soft); }
.about p:last-child { margin-bottom: 0; }
.about a { color: var(--c0); }
.about-meta {
  font-family: var(--font-label);
  font-size: 11.5px;
  letter-spacing: .04em;
  color: var(--ink-faint);
}

body.locked .board-grid, body.locked .factories, body.locked .center-dish { cursor: progress; }
.hidden { display: none !important; }

/* -------------------------------------------------------------- responsive */
@media (max-width: 1080px) {
  .below { grid-template-columns: minmax(0, 1fr); }
  .status { flex-wrap: wrap; }
}

@media (max-width: 720px) {
  /* Phone layout: the boards are the page, one above the other so neither of
   * them has to shrink below a playable tile. Every control keeps a 44px target. */
  .topbar { gap: 6px 10px; padding: 8px 10px; }
  .brand { width: 100%; margin-right: 0; gap: 8px; }
  .brand-name { font-size: 19px; }
  .brand-sub { font-size: 11px; }
  /* seed, "you go first" and Deal share one row: the band, smaller */
  .setup { width: 100%; gap: 6px 8px; align-items: center; flex-wrap: nowrap; }
  .setup .btn { flex: 0 0 auto; padding: 10px 11px; white-space: nowrap; }
  .setup .field { flex: 0 1 100px; }
  .setup .field .field-label { display: none; }
  .setup .check { flex: 0 0 auto; }
  .field select, .field input { min-width: 0; padding: 9px 8px; }
  .field-narrow select, .field-narrow input { width: auto; min-width: 0; }
  .btn { padding: 10px 14px; min-height: 44px; }
  .engine-bar { padding: 5px 10px; font-size: 11px; gap: 4px 10px; }
  .engine-text { min-width: 0; }
  /* the settings and the navigator are controls, so they get a tap target too */
  .gear, .speed, .nav-btn { min-height: 44px; }
  .settings-panel { gap: 8px 12px; }
  .check { padding-bottom: 0; min-height: 44px; }
  .check input { width: 20px; height: 20px; }

  .table { padding: 8px 8px 32px; gap: 8px; }
  .panel { padding: 11px 11px 13px; }
  .scoring-grid { grid-template-columns: minmax(0, 1fr); }
  .log { max-height: 190px; }

  /* the status band earns its keep in one small line, not a headline */
  .status { padding: 8px 12px 10px; gap: 10px; }
  .status-headline { font-size: 15px; }
  .status-detail { font-size: 10.5px; margin-top: 2px; min-height: 0; }
  .status-side { min-width: 40px; }
  .status-side-score { font-size: 19px; }
  .status-dash { font-size: 15px; }

  /* stack (+): the old phone table — one big board under the other */
  body[data-boards="stack"] .boards { grid-template-columns: minmax(0, 1fr); }
  body[data-boards="stack"] .board { --tile: clamp(26px, 9vw, 38px); }
  body[data-boards="stack"] .factories { gap: 10px 12px; }
  body[data-boards="stack"] .factory { --dish-size: calc(var(--tile) * 2 + 22px); }
  body[data-boards="stack"] .middle-table { --tile: clamp(24px, 8vw, 32px); }
  body[data-boards="stack"] .board-grid { column-gap: 8px; }
  body[data-boards="stack"] .line { padding: 0 2px; }
  body[data-boards="stack"] .line .row-note { font-size: 10.5px; line-height: 1.15; }

  /* side (−, the default): factories left, both boards beside them. Small
   * tiles are the accepted price of seeing the whole game at once. */
  body:not([data-boards="stack"]) .playfield {
    grid-template-columns: minmax(0, 1.04fr) minmax(0, .96fr);
    gap: 6px;
  }
  body:not([data-boards="stack"]) .boards { grid-template-columns: minmax(0, 1fr); gap: 6px; }
  body:not([data-boards="stack"]) .board {
    --tile: clamp(11px, calc((48vw - 50px) / 10), 38px);
    padding: 7px 6px 8px;
    gap: 6px;
  }
  body:not([data-boards="stack"]) .board-grid { column-gap: 3px; }
  body:not([data-boards="stack"]) .line { padding: 0 1px; gap: 2px; }
  body:not([data-boards="stack"]) .line .row-note { display: none; }
  body:not([data-boards="stack"]) .wall-row { gap: 2px; padding: 0 3px; }
  body:not([data-boards="stack"]) .board-head { column-gap: 6px; padding-bottom: 5px; }
  body:not([data-boards="stack"]) .board-who { font-size: 10px; letter-spacing: .1em; }
  body:not([data-boards="stack"]) .board-score { font-size: 18px; }
  body:not([data-boards="stack"]) .board-notes { font-size: 9.5px; min-height: 12px; }
  body:not([data-boards="stack"]) .floor { padding: 3px 2px; gap: 2px; }
  body:not([data-boards="stack"]) .floor .pen { font-size: 8.5px; }
  body:not([data-boards="stack"]) .middle-panel { padding: 8px 6px 10px; }
  body:not([data-boards="stack"]) .middle-table { --tile: clamp(17px, 5.6vw, 32px); }
  body:not([data-boards="stack"]) .factories { gap: 8px 8px; }
  body:not([data-boards="stack"]) .factory { --dish-size: calc(var(--tile) * 2 + 16px); }
  body:not([data-boards="stack"]) .center-dish { padding: 8px 10px; margin-top: 8px; }
}

@media (max-width: 420px) {
  body[data-boards="stack"] .board { --tile: clamp(23px, 10vw, 34px); }
  body[data-boards="stack"] .middle-table { --tile: clamp(21px, 8.5vw, 28px); }
  .engine-badge { font-size: 10px; letter-spacing: .08em; }
  .status { gap: 8px; }
}

/* A coarse pointer never hovers, so the hover lift just makes taps feel laggy. */
@media (hover: none) {
  button.tile:hover { transform: none; }
  button.line.open:hover { background: var(--c4-wash); filter: none; }
}

/* ========================================================== corner buttons ==
 * Two small round buttons pinned to the bottom-right, the way every board-game
 * site pins its "?" — one scrolls to the What-this-is panel, one opens the
 * public tally. Fixed, but tiny: they float over the linen, never the table. */
.corner {
  position: fixed;
  right: 14px;
  bottom: 14px;
  z-index: 20;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.corner-btn {
  width: 42px;
  height: 42px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--grout);
  border-radius: 50%;
  background: linear-gradient(var(--btn-top), var(--btn-bottom));
  box-shadow: var(--shadow-tile);
  cursor: pointer;
  color: var(--ink-soft);
  font-family: var(--font-display);
  font-size: 21px;
  line-height: 1;
  text-decoration: none;
}
.corner-btn:hover {
  background: linear-gradient(var(--btn-top-hover), var(--btn-bottom-hover));
  color: var(--ink);
}
.corner-btn svg { width: 18px; height: 18px; fill: currentColor; display: block; }

/* the "?" button's landing: the panel it scrolled to glows for a breath */
.about.lit { box-shadow: var(--shadow-panel), 0 0 0 3px var(--c4-wash); }
.about { transition: box-shadow .5s ease; }
