/* Shared design tokens and the app shell.
 *
 * House style, matching the rest of this repo: plain CSS, no build step, no
 * framework. Light/dark comes from `prefers-color-scheme` by default and is
 * overridable by a `data-theme` attribute on <html>, persisted in
 * localStorage - the same mechanism shared/web/theme.js uses everywhere in
 * this project.
 *
 * General-purpose tokens (surface/text/border/accent/status colors) now
 * live in shared/web/styles/tokens.css - shared project-wide since the
 * single-PWA work (plans/project-wide-pwa.md, decision 4), which settled on
 * Wordfeud Butler's green/cream palette rather than this app's old
 * blue/neutral one. This file keeps this app's historical variable names
 * (--fg, --card, --good, etc. - every rule in this file and board.css/
 * quiz.css already reads them) as a thin alias layer onto the shared
 * tokens' names, rather than rewriting every rule to the shared names
 * directly - far less risky than a project-wide search-and-replace across
 * three CSS files. --sq-* (the board's bonus-square colors) and the
 * --tile-* set are NOT aliased: they are semantic game-state/rendering
 * colors, not brand tokens, and keep their own hardcoded values exactly as
 * before.
 *
 * Component CSS lives in its own file next to this one (board.css,
 * quiz.css). Everything in all three is built from the custom properties
 * below; a component file should not hardcode a colour (--sq-* and --tile-*
 * excepted, per above).
 */
@import url("/shared/styles/tokens.css");
@import url("/shared/styles/pull-to-refresh.css");

:root {
  /* --bg, --border, --accent and --warn are not listed here: this app happened to already use
     those exact names, so they inherit straight from the imported tokens.css with no alias
     needed - redeclaring --bg: var(--bg) here would be a cyclic reference (invalid CSS), not an
     alias. Only the names that actually differ need one. */
  --fg: var(--text);
  --muted: var(--text-muted);
  --accent-fg: var(--accent-contrast);
  --card: var(--surface);
  --card-raised: var(--surface-2);

  --good: var(--positive);
  --bad: var(--negative);

  /* Tiles and squares - semantic/rendering colors, not part of the shared brand palette. */
  --tile-bg: #f3e2be;
  --tile-fg: #2a1e0d;
  --tile-edge: #cdb98f;
  --tile-pending: #ffd98a;
  --tile-blank-fg: #8a6d3b;
  --sq-plain: #e9e5dc;
  --sq-dl: #a8c8f0;
  --sq-tl: #3f7fd0;
  --sq-dw: #f0b8a8;
  --sq-tw: #d05a3f;
  --sq-center: #d8cfbc;
  --sq-fg: #33302a;
  --sq-fg-strong: #ffffff;

  --radius: 8px;
  --gap: 0.75rem;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --tile-bg: #d9c69f;
    --tile-fg: #241a0b;
    --tile-edge: #8c7c58;
    --tile-pending: #ffcf70;
    --tile-blank-fg: #6d5426;
    --sq-plain: #3b3a36;
    --sq-dl: #2d4d78;
    --sq-tl: #1f5fa8;
    --sq-dw: #7a4032;
    --sq-tw: #a83c25;
    --sq-center: #4a463d;
    --sq-fg: #d8d4cb;
    --sq-fg-strong: #ffffff;
  }
}

/* The explicit toggle wins over the media query, in both directions. --fg/--bg/etc. need no
   [data-theme] override here at all: they are var() aliases onto the shared tokens, which already
   switch on [data-theme] themselves (shared/web/styles/tokens.css) - only --sq-* and --tile-*
   (not shared) need repeating per explicit theme. */
:root[data-theme="light"] {
  --tile-bg: #f3e2be;
  --tile-fg: #2a1e0d;
  --tile-edge: #cdb98f;
  --tile-pending: #ffd98a;
  --tile-blank-fg: #8a6d3b;
  --sq-plain: #e9e5dc;
  --sq-dl: #a8c8f0;
  --sq-tl: #3f7fd0;
  --sq-dw: #f0b8a8;
  --sq-tw: #d05a3f;
  --sq-center: #d8cfbc;
  --sq-fg: #33302a;
}

:root[data-theme="dark"] {
  --tile-bg: #d9c69f;
  --tile-fg: #241a0b;
  --tile-edge: #8c7c58;
  --tile-pending: #ffcf70;
  --tile-blank-fg: #6d5426;
  --sq-plain: #3b3a36;
  --sq-dl: #2d4d78;
  --sq-tl: #1f5fa8;
  --sq-dw: #7a4032;
  --sq-tw: #a83c25;
  --sq-center: #4a463d;
  --sq-fg: #d8d4cb;
}

* { box-sizing: border-box; }

body {
  margin: 0 auto;
  /* Bottom padding accounts for the home-indicator safe area on a notched/rounded-corner phone —
     env() falls back to 0px where it's unsupported, so this is exactly 3rem everywhere else
     (Wordfeud Butler's header already does the equivalent for the top inset;
     index.html's own viewport meta already sets viewport-fit=cover, needed for env() to report
     anything other than 0 at all). */
  padding: 0.75rem 0.75rem calc(3rem + env(safe-area-inset-bottom, 0px));
  max-width: 780px;
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  background: var(--bg);
  color: var(--fg);
  line-height: 1.4;
}

h1 { font-size: 1.15rem; margin: 0; }
h2 { font-size: 1rem; margin: 0 0 0.4rem; }

a { color: var(--accent); }

/* --- generic controls ------------------------------------------------------ */

button {
  font: inherit;
  font-size: 0.95rem;
  padding: 0.4rem 0.8rem;
  border: 1px solid var(--accent);
  border-radius: 6px;
  background: var(--accent);
  color: var(--accent-fg);
  cursor: pointer;
}
button.secondary {
  background: transparent;
  color: var(--accent);
}
button.quiet {
  background: transparent;
  color: var(--muted);
  border-color: var(--border);
}
button.danger { background: var(--bad); border-color: var(--bad); color: #fff; }
button:disabled { opacity: 0.45; cursor: not-allowed; }

input[type="text"] {
  font: inherit;
  padding: 0.4rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--fg);
  min-width: 0;
}
input[type="number"] {
  font: inherit;
  padding: 0.4rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--fg);
  width: 5rem;
}

.card {
  border: 1px solid var(--border);
  background: var(--card);
  border-radius: var(--radius);
  padding: 0.8rem;
  margin-bottom: 0.75rem;
}

.row { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; }
.muted { color: var(--muted); }
.small { font-size: 0.85rem; }
.hidden { display: none !important; }

.notice {
  border-left: 3px solid var(--accent);
  padding: 0.4rem 0.6rem;
  background: var(--card);
  border-radius: 0 var(--radius) var(--radius) 0;
  margin-bottom: 0.5rem;
  font-size: 0.9rem;
}
.notice.bad { border-left-color: var(--bad); color: var(--bad); }
.notice.good { border-left-color: var(--good); }
.notice.warn { border-left-color: var(--warn); }

/* --- credentials, shown exactly once --------------------------------------- */

.credentials {
  border: 2px dashed var(--warn);
  border-radius: var(--radius);
  padding: 0.8rem;
  margin-bottom: 0.75rem;
  background: var(--card-raised);
}
.credentials dl { margin: 0.5rem 0 0; display: grid; grid-template-columns: auto 1fr; gap: 0.3rem 0.8rem; }
.credentials dt { color: var(--muted); font-size: 0.85rem; }
.credentials dd { margin: 0; font-family: ui-monospace, "SFMono-Regular", Menlo, monospace; font-size: 1.05rem; }

/* --- scoreboard ------------------------------------------------------------ */

.scoreboard { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.scoreboard .side {
  flex: 1 1 8rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.5rem 0.6rem;
  background: var(--card);
}
.scoreboard .side.active { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.scoreboard .name { font-weight: 600; font-size: 0.9rem; word-break: break-word; }
.scoreboard .score { font-size: 1.5rem; line-height: 1.1; }
.scoreboard .cp { font-size: 0.8rem; color: var(--muted); }
.scoreboard .cp .out { color: var(--bad); }

/* --- game list / opponent search ------------------------------------------- */

.list { list-style: none; margin: 0; padding: 0; }
.list li {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.45rem 0;
  border-bottom: 1px solid var(--border);
}
.list li:last-child { border-bottom: 0; }
.list .grow { flex: 1; min-width: 0; }
.list .sub { color: var(--muted); font-size: 0.8rem; }
.list .turn-dot {
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  background: var(--border);
  flex: none;
}
.list .turn-dot.yours { background: var(--good); }

.card details { margin-top: 0.6rem; }
.card details summary { cursor: pointer; }
.card details .list { margin-top: 0.4rem; }

/* "+ New game" (lobby.js) is a disclosure like the others above, but it is
   the card's one primary action rather than a secondary aside, so its
   summary reads like a button/heading — larger, bold, accent-colored —
   instead of the small muted toggles used for "Game settings" / "Completed
   games". The native marker is left as-is (same triangle as those other
   toggles) to show open/closed state; the text itself does not change. */
.card .new-game { margin-top: 0; }
.new-game > summary {
  font-size: 1rem;
  font-weight: 600;
  color: var(--accent);
}
.new-game[open] > summary { margin-bottom: 0.6rem; }

/* --- the two modals the shell owns ------------------------------------------
 *
 * The overlay and panel styling is quiz.css's `.quiz-overlay`/`.quiz-modal`,
 * reused rather than duplicated: the blank-tile chooser and the swap picker
 * are the same kind of object as the quiz, and a second overlay style would
 * only be a second thing to keep in step. What is added here is the letter
 * grid, which is theirs alone.
 */

.blank-letters {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(2.75rem, 1fr));
  gap: 0.4rem;
  margin: 0.75rem 0;
}

.blank-letter {
  font-size: 1.1rem;
  font-weight: 600;
  padding: 0.55rem 0.25rem;
  background: var(--tile-bg);
  color: var(--tile-fg);
  border: 1px solid var(--tile-edge);
  border-radius: 6px;
  cursor: pointer;
}
.blank-letter:hover { border-color: var(--accent); }
.blank-letter:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.blank-letter.chosen {
  background: var(--tile-pending);
  border-color: var(--accent);
  box-shadow: inset 0 0 0 2px var(--accent);
}

/* A flexible gap in a .row. The top bar has its own rule for the same class;
 * this is the general one, used under the board and in the lobby's headers. */
.spacer { flex: 1 1 auto; }

/* The action bar under the board wraps rather than scrolling: on a phone six
 * buttons do not fit on one line, and a horizontally scrolling toolbar hides
 * the ones that matter. */
#actions { gap: 0.4rem 0.5rem; margin-top: 0.6rem; }
#actions button { flex: 0 1 auto; }

#move-hint { margin: 0.4rem 0 0; min-height: 1.2em; }
#status { margin: 0.5rem 0; }

/* --- this game's own rules, collapsed by default ---------------------------- */

.game-rules { margin-top: 0.8rem; }
.game-rules summary { cursor: pointer; }
#game-rules-list {
  margin: 0.5rem 0 0;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.3rem 0.8rem;
}
#game-rules-list dt { color: var(--muted); font-size: 0.85rem; }
#game-rules-list dd { margin: 0; }
#notices { position: sticky; top: 0; z-index: 5; }

/* The offline indicator: deliberately small and quiet. It says the socket is
 * down and being retried (connection.js's backoff); the buttons that would
 * otherwise queue a move silently are disabled meanwhile (app.js). */
.connection-state {
  margin: 0 0 0.5rem;
  padding: 0.25rem 0.6rem;
  font-size: 0.8rem;
  color: var(--muted);
  border-left: 3px solid var(--warn);
  background: var(--card);
  border-radius: 0 var(--radius) var(--radius) 0;
}
