:root {
  --bg: #101210;
  --panel: #191c17;
  --panel-2: #1f231d;
  --line: #2f342c;
  --line-soft: #262a23;
  --text: #eae7dd;
  --muted: #97a08e;
  --accent: #a8c283;
  --accent-strong: #bcd897;
  --danger: #f0a89e;
  --gap: 12px;
  --radius: 11px;
  --panel-width: clamp(300px, 26vw, 372px);
  color-scheme: dark;
  font-family: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  font-synthesis: none;
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;
  /* Touch screens: no double-tap zoom to swallow taps on the board, and no
     pull-to-refresh to fire when a piece is dragged from the top rank. Pinch
     zoom is deliberately still allowed. */
  touch-action: manipulation;
  overscroll-behavior: none;
  color: var(--text);
  background:
    radial-gradient(circle at 12% -8%, rgba(120, 146, 92, .16), transparent 40rem),
    linear-gradient(160deg, #171a15, #0d0f0c 70%);
}

button, select, input, textarea { font: inherit; color: inherit; }
h1, h2, p { margin: 0; }

.app {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  height: 100dvh;
}

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

.topbar {
  display: flex;
  align-items: center;
  gap: var(--gap);
  padding: 8px 14px;
  border-bottom: 1px solid var(--line-soft);
  background: rgba(15, 17, 14, .8);
}

.brand {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: .95rem;
  font-weight: 700;
  letter-spacing: -.01em;
  white-space: nowrap;
}
.brand .mark { color: var(--accent); font-size: 1.3rem; line-height: 1; }

.modes {
  display: flex;
  gap: 2px;
  margin-inline: auto;
  padding: 3px;
  background: #14170f;
  border: 1px solid var(--line-soft);
  border-radius: 999px;
}

.mode {
  padding: 5px 15px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-size: .82rem;
  font-weight: 650;
  cursor: pointer;
  transition: background .15s, color .15s;
}
.mode:hover { color: var(--text); }
.mode.is-active { background: var(--accent); color: #10130d; }

.topbar-right { display: flex; align-items: center; gap: 6px; }

.badge {
  padding: 4px 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--muted);
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* ------------------------------------------------------------------ layout */

.layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--panel-width);
  gap: var(--gap);
  min-height: 0;
  padding: var(--gap);
}

.board-area {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 8px;
  min-height: 0;
  min-width: 0;
  /* A window too small for the smallest board clips it rather than letting it
     spill over the panel. */
  overflow: hidden;
}

/* The stack exists for the phone layout, where the move strip, the player rows
   and the status line sit tight against the board. On a wide screen those live
   in the panel instead and this is simply a wrapper around the board. */
.board-stack {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  min-height: 0;
  min-width: 0;
}
.move-strip, .player-strip, .board-status, .engine-strip,
.mobilebar, .sheet-grip, .sheet-backdrop { display: none; }

/* The board is sized from this column in JS, so the holder must not claim the
   spare height itself — otherwise the toolbar drifts away from the board. */
.board-holder {
  display: flex;
  flex: 0 1 auto;
  gap: 10px;
  align-items: center;
  justify-content: center;
  min-height: 0;
}

#board {
  /* JS gives the board a size; flexing it from there would only ever make it
     non-square, and chessground draws squares as a share of each axis. */
  flex: none;
  /* Hand every touch that starts on a square to the board itself. Without this
     the browser can read the first touch as a scroll/zoom gesture and swallow
     it, so the first drag of a piece silently fails to register. */
  touch-action: none;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 18px 46px rgba(0, 0, 0, .5), 0 0 0 1px rgba(255, 255, 255, .06);
}

/* Chessground positions coordinates in the margin around the board; ours is
   clipped to its own edges, so bring them inside and size them with it. */
#board coords {
  z-index: 3;  /* Above the pieces they share the outer squares with. */
  font-size: clamp(9px, calc(var(--board-size, 480px) / 46), 16px);
  line-height: 1;
  opacity: 1;
}
#board coords.ranks { top: 0; left: 3px; width: auto; height: 100%; }
#board coords.ranks coord { display: block; transform: none; }
/* A definite height with the letters sitting on its floor: `auto` collapsed to
   just under one line box and cropped the descender off every letter. */
#board coords.files {
  bottom: 1px;
  left: 0;
  width: 100%;
  height: 1.25em;
  padding: 0 4px;
  align-items: flex-end;
}
#board coords coord {
  color: rgba(48, 38, 24, .78);
  font-weight: 700;
  text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
}

/* ---------------------------------------------------------------- eval bar */

.evalbar {
  position: relative;
  width: 20px;
  flex: none;
  overflow: hidden;
  background: #2a2d26;
  border: 1px solid var(--line);
  border-radius: 5px;
  transition: opacity .2s;
}
.evalbar[hidden] { display: none; }

.evalbar-fill {
  position: absolute;
  inset: auto 0 0 0;
  height: calc(var(--eval-share, 50) * 1%);
  background: linear-gradient(180deg, #f4f2ea, #d9d6c9);
  transition: height .35s cubic-bezier(.2, .7, .3, 1), width .35s cubic-bezier(.2, .7, .3, 1);
}
.evalbar.flipped .evalbar-fill { inset: 0 0 auto 0; }

/* Lying down, the bar costs height instead of board width — on a phone that is
   the cheaper of the two, because the board is limited by width there. */
.evalbar.horizontal { width: 100%; height: 9px; border-radius: 999px; }
.evalbar.horizontal .evalbar-fill {
  inset: 0 auto 0 0;
  width: calc(var(--eval-share, 50) * 1%);
  height: 100%;
  background: linear-gradient(90deg, #f4f2ea, #d9d6c9);
}
.evalbar.horizontal.flipped .evalbar-fill { inset: 0 0 0 auto; }
.evalbar.horizontal .evalbar-value { display: none; }

.evalbar-value {
  position: absolute;
  inset: auto 0 3px 0;
  color: #2b2f27;
  font: 700 .62rem/1 ui-monospace, SFMono-Regular, Menlo, monospace;
  text-align: center;
}
/* Held over from an earlier ply while this position is still being searched —
   an honest number, but not this one's, so it is dimmed until it firms up. */
.evalbar.stale .evalbar-value { opacity: .4; }
.evalbar.flipped .evalbar-value { inset: 2px 0 auto 0; }
.evalbar.low .evalbar-value { color: #e8e5db; inset: 2px 0 auto 0; }
.evalbar.flipped.low .evalbar-value { inset: auto 0 2px 0; }

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

.board-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  justify-content: center;
  flex: none;
}

.nav-group {
  display: flex;
  gap: 4px;
  align-items: center;
  padding: 3px;
  background: var(--panel);
  border: 1px solid var(--line-soft);
  border-radius: 9px;
}

.ply-readout {
  min-width: 62px;
  color: var(--muted);
  font: 600 .74rem ui-monospace, SFMono-Regular, Menlo, monospace;
  text-align: center;
}

.icon-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 30px;
  height: 28px;
  padding: 0 7px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--muted);
  font-size: .82rem;
  line-height: 1;
  cursor: pointer;
  text-decoration: none;
  transition: background .14s, color .14s;
}
.icon-button:hover:not(:disabled) { background: #2b3027; color: var(--text); }

.chip-button {
  height: 28px;
  padding: 0 10px;
  white-space: nowrap;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--muted);
  font-size: .76rem;
  font-weight: 650;
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  transition: background .14s, color .14s;
}
.chip-button:hover:not(:disabled) { background: #2b3027; color: var(--text); }
button:disabled, .icon-button:disabled { opacity: .4; cursor: not-allowed; }

/* Phone-only; the panel carries these actions on a wide screen. */
.quick-action { display: none; }

/* ------------------------------------------------------------------- panel */

.panel {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: #3a4033 transparent;
}

.panel-tabs { display: none; gap: 2px; padding: 3px; background: #14170f; border: 1px solid var(--line-soft); border-radius: 9px; }
.panel-tab {
  flex: 1;
  padding: 6px 8px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--muted);
  font-size: .78rem;
  font-weight: 650;
  cursor: pointer;
}
.panel-tab.is-active { background: #2e3429; color: var(--text); }

.card {
  flex: none;
  padding: 12px 13px;
  background: var(--panel);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
}

.card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 9px;
}
.card-head-actions { display: flex; gap: 2px; flex: none; }
.card-head h2 { overflow: hidden; text-overflow: ellipsis; }

h2 {
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #b3bda6;
}

/* players + status */

.players-card { display: grid; gap: 5px; }

.player {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: .82rem;
}
.player .dot, .player-strip .dot {
  width: 8px;
  height: 8px;
  flex: none;
  border-radius: 50%;
  background: #3d4437;
  transition: background .2s, box-shadow .2s;
}
.player.to-move .dot, .player-strip.to-move .dot {
  background: var(--accent);
  box-shadow: 0 0 10px rgba(168, 194, 131, .8);
}
.player-name { font-weight: 650; }
.material { color: var(--accent); font: 700 .72rem ui-monospace, SFMono-Regular, Menlo, monospace; }
.player-tag {
  margin-left: auto;
  overflow: hidden;
  color: var(--muted);
  font-size: .74rem;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 62%;
  text-align: right;
}

.status {
  margin-top: 5px;
  padding-top: 8px;
  border-top: 1px solid var(--line-soft);
  color: var(--muted);
  font-size: .8rem;
}
.status.thinking { color: var(--accent); }
.status.over { color: #e3c887; }

/* controls */

.controls-card { display: grid; gap: 10px; }
.field-row { display: flex; gap: 8px; }
.field { flex: 1; min-width: 0; }
.field[hidden], .field-row[hidden], .button-row [hidden] { display: none; }

label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  margin-bottom: 5px;
  color: var(--muted);
  font-size: .7rem;
  font-weight: 650;
  letter-spacing: .04em;
  text-transform: uppercase;
}
label output { font: 700 .72rem ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--text); }

select {
  width: 100%;
  height: 34px;
  padding: 0 9px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #12140f;
  text-overflow: ellipsis;
}
select.mini { width: auto; height: 26px; padding: 0 6px; font-size: .74rem; }
select:focus-visible, button:focus-visible, input:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

input[type="range"] {
  width: 100%;
  height: 34px;
  margin: 0;
  accent-color: var(--accent);
}

.button-row { display: flex; gap: 8px; }

.primary, .secondary, .ghost {
  flex: 1;
  min-height: 36px;
  padding: 0 12px;
  border: 1px solid transparent;
  border-radius: 8px;
  font-size: .82rem;
  font-weight: 700;
  cursor: pointer;
  transition: filter .14s, transform .14s;
}
.primary { background: var(--accent); color: #10130d; }
.secondary { background: #2b3027; color: var(--text); border-color: #383e32; }
.ghost { background: transparent; color: var(--muted); border-color: var(--line); }
.primary:hover:not(:disabled), .secondary:hover:not(:disabled), .ghost:hover:not(:disabled) {
  filter: brightness(1.1);
}
.primary:active:not(:disabled), .secondary:active:not(:disabled) { transform: translateY(1px); }

/* analysis */

.lines { display: grid; gap: 3px; margin: 0; padding: 0; list-style: none; max-height: 27vh; overflow-y: auto; }
.line {
  position: relative;
  display: grid;
  grid-template-columns: 1.1rem minmax(0, 1fr) auto;
  gap: 8px;
  align-items: center;
  padding: 5px 8px;
  border-radius: 7px;
  background: var(--panel-2);
  overflow: hidden;
  cursor: pointer;
}
.line:hover { background: #262b21; }
.line.best { box-shadow: inset 0 0 0 1px rgba(168, 194, 131, .45); }
.line-bar {
  position: absolute;
  inset: 0 auto 0 0;
  background: linear-gradient(90deg, rgba(168, 194, 131, .26), rgba(168, 194, 131, .07));
  pointer-events: none;
}
.line > :not(.line-bar) { position: relative; }
.line-rank { color: #6f7866; font: 700 .68rem ui-monospace, monospace; }
.line-san { font-weight: 700; font-size: .84rem; }
.line-policy { color: var(--muted); font: 600 .68rem ui-monospace, monospace; margin-left: 6px; }
.line-value { font: 700 .78rem ui-monospace, monospace; color: #dfe8d0; }
.line-empty, .empty { padding: 6px 2px; color: #71796a; font-size: .78rem; }

/* moves */

.moves-card { display: flex; flex-direction: column; min-height: 96px; flex: 1 1 auto; }

.eval-graph {
  width: 100%;
  height: 44px;
  flex: none;
  margin-bottom: 8px;
  background: #14170f;
  border-radius: 6px;
  cursor: pointer;
}
.eval-graph[hidden] { display: none; }
.eval-graph-area { fill: rgba(224, 230, 210, .82); stroke: none; }
.eval-graph-zero { stroke: #4a5142; stroke-width: 1; vector-effect: non-scaling-stroke; }
.eval-graph-cursor { stroke: var(--accent); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.moves-scroll { overflow-y: auto; min-height: 0; scrollbar-width: thin; }

.move-grid { display: grid; grid-template-columns: 2.1rem 1fr 1fr; gap: 1px 4px; align-items: center; }
.move-number { color: #6c7565; font: 600 .72rem ui-monospace, monospace; }
.move {
  display: flex;
  align-items: baseline;
  gap: 5px;
  padding: 3px 6px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  font-size: .82rem;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
  width: 100%;
}
.move:hover { background: #262b21; }
.move.current { background: #384030; color: #f0f4e6; }
.move-glyph { color: #dd9a86; font-weight: 800; font-size: .78rem; }
.move-eval { margin-left: auto; color: #7f8a74; font: 600 .66rem ui-monospace, monospace; }
.move.current .move-eval { color: #b9c9a3; }

.error {
  flex: none;
  padding: 10px 12px;
  border: 1px solid #6d4640;
  border-radius: var(--radius);
  background: rgba(78, 35, 31, .6);
  color: var(--danger);
  font-size: .8rem;
}

/* ----------------------------------------------------------------- dialogs */

dialog.sheet {
  width: min(420px, calc(100vw - 32px));
  padding: 20px;
  color: var(--text);
  background: #1c1f19;
  border: 1px solid #3b4136;
  border-radius: 14px;
  box-shadow: 0 30px 90px rgba(0, 0, 0, .7);
}
dialog.wide { width: min(560px, calc(100vw - 32px)); }
dialog::backdrop { background: rgba(0, 0, 0, .66); backdrop-filter: blur(3px); }
dialog h2 { margin-bottom: 12px; }
dialog .button-row { margin-top: 14px; }
.hint { margin-bottom: 8px; color: var(--muted); font-size: .78rem; line-height: 1.5; }
.hint code { background: #24281f; padding: 1px 5px; border-radius: 4px; font-size: .74rem; }

textarea {
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: #12140f;
  font: .78rem/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
  resize: vertical;
}

.dialog-error { margin-top: 8px; color: var(--danger); font-size: .78rem; }

.switch {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 10px;
  margin-bottom: 2px;
  padding: 7px 2px;
  color: var(--text);
  font-size: .84rem;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  cursor: pointer;
}
.switch input { width: 17px; height: 17px; accent-color: var(--accent); }

.promotion-pieces { display: flex; gap: 8px; justify-content: center; }
.promotion-pieces button {
  width: 56px;
  height: 56px;
  padding: 0;
  border: 1px solid #3d4336;
  border-radius: 10px;
  background: #2b3027;
  color: #f2f0e9;
  font-size: 2rem;
  cursor: pointer;
}
.promotion-pieces button:hover { background: #363c30; }
.black-to-promote .promotion-pieces button { color: #14170f; background: #cdd2c1; border-color: #b6bcab; }
.black-to-promote .promotion-pieces button:hover { background: #dde2d1; }

.shortcuts { display: grid; gap: 6px; margin: 0; padding: 0; list-style: none; font-size: .8rem; }
.shortcuts li { display: flex; align-items: center; gap: 8px; }
.shortcuts span { margin-left: auto; color: var(--muted); font-size: .76rem; text-align: right; }
kbd {
  padding: 2px 7px;
  border: 1px solid #454b3d;
  border-bottom-width: 2px;
  border-radius: 5px;
  background: #24281f;
  font: 600 .72rem ui-monospace, monospace;
}

/* ------------------------------------------------------------------- toast */

.toast {
  position: fixed;
  left: 50%;
  top: 58px;
  transform: translateX(-50%);
  padding: 9px 16px;
  border: 1px solid #3d4336;
  border-radius: 999px;
  background: #23281e;
  box-shadow: 0 12px 30px rgba(0, 0, 0, .5);
  font-size: .8rem;
  animation: rise .18s ease-out;
  z-index: 40;
}
@keyframes rise { from { opacity: 0; transform: translate(-50%, -8px); } }

/* -------------------------------------------------------------- responsive */

@media (max-width: 980px) {
  :root { --panel-width: 300px; }
  .brand span:not(.mark) { display: none; }
}

/* Stack only where stacking wins. Under the panel the board is limited by the
   window's width, beside it by the window's height minus much less chrome, so
   a window taller than it is wide gets a bigger board stacked and every other
   window gets a bigger board with the panel beside it — a phone held sideways
   included.

   Everything below serves one goal — give the board every pixel. The panel
   stops being a column and becomes a sheet that slides over the board on
   demand, the eval bar lies down so it costs height rather than width, and
   what remains on screen (move strip, player rows, status) is thin and sits
   flush against the board.

   app.js repeats this query to size the board; change both together. */
@media (max-width: 820px) and (max-aspect-ratio: 1 / 1), (max-aspect-ratio: 4 / 5) {
  /* Placed explicitly: the move strip disappears when a game has no moves yet,
     and auto placement would then hand its row to the board. */
  .app { grid-template-rows: auto auto minmax(0, 1fr) auto; }
  .topbar { grid-row: 1; }
  .move-strip { grid-row: 2; }
  .layout { grid-row: 3; }
  .mobilebar { grid-row: 4; }

  .layout {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
    padding: 0;
  }

  /* The board group hugs itself and floats in the middle of what is left. */
  .board-area { justify-content: center; overflow: hidden; }
  .board-stack { flex: 0 1 auto; }
  .board-holder { flex: 0 1 auto; flex-direction: column; gap: 4px; }
  #board { border-radius: 0; box-shadow: 0 6px 22px rgba(0, 0, 0, .45); }

  .move-strip {
    display: flex;
    flex: none;
    gap: 2px;
    align-items: center;
    height: 30px;
    padding: 0 6px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    border-bottom: 1px solid var(--line-soft);
  }
  .move-strip::-webkit-scrollbar { display: none; }
  .move-strip:empty { display: none; }
  .strip-move {
    flex: none;
    padding: 4px 7px;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: var(--muted);
    font-size: .8rem;
    font-weight: 650;
    white-space: nowrap;
    cursor: pointer;
  }
  .strip-move.current { background: #384030; color: #f0f4e6; }
  .strip-number { color: #6c7565; font-size: .72rem; margin-right: 3px; }

  .player-strip {
    display: flex;
    flex: none;
    gap: 8px;
    align-items: center;
    height: 30px;
    padding: 0 10px;
    font-size: .84rem;
  }
  .player-strip .player-name { font-weight: 650; }
  .player-strip .captured {
    overflow: hidden;
    color: #6f7565;
    font-size: .82rem;
    letter-spacing: -2px;
    white-space: nowrap;
  }
  .player-strip .captured.light { color: #cfcbbc; }
  .player-strip .material { margin-left: 2px; }

  .board-status {
    display: block;
    flex: none;
    height: 17px;
    padding: 0 10px;
    overflow: hidden;
    color: var(--muted);
    font-size: .74rem;
    line-height: 17px;
    text-align: center;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .board-status.thinking { color: var(--accent); }
  .board-status.over { color: #e3c887; }

  /* Only the actions that have no home in the bottom bar stay under the board:
     the bar covers step-by-step navigation, so just the two jumps remain. */
  .board-toolbar { flex: none; flex-wrap: wrap; gap: 6px; padding: 5px 8px 0; }
  .board-toolbar #nav-prev, .board-toolbar #nav-next, .board-toolbar .ply-readout { display: none; }

  .quick-action {
    display: inline-flex;
    align-items: center;
    height: 34px;
    padding: 0 16px;
    border: 0;
    border-radius: 8px;
    background: var(--accent);
    color: #10130d;
    font-size: .82rem;
    font-weight: 700;
    white-space: nowrap;
    cursor: pointer;
  }
  .quick-action[hidden] { display: none; }
  .board-toolbar .chip-button, .board-toolbar .icon-button { height: 34px; }
  .board-toolbar .chip-button { padding: 0 14px; font-size: .8rem; }
  .board-toolbar .icon-button { min-width: 40px; }

  /* Above the sheet, so the same button that opened a section can close it. */
  .mobilebar {
    display: grid;
    position: relative;
    z-index: 31;
    grid-template-columns: repeat(5, 1fr);
    padding-bottom: env(safe-area-inset-bottom, 0);
    border-top: 1px solid var(--line-soft);
    background: rgba(18, 21, 16, .96);
  }
  .bar-button {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    min-height: 52px;
    padding: 4px 0;
    border: 0;
    background: transparent;
    color: var(--muted);
    font-size: .66rem;
    font-weight: 650;
    letter-spacing: .02em;
    cursor: pointer;
  }
  .bar-button .bar-icon { font-size: 1.05rem; line-height: 1; }
  .bar-button:disabled { opacity: .35; }
  .bar-button.is-open { color: var(--accent); }

  /* The panel slides up over the board instead of competing with it. */
  .panel {
    position: fixed;
    inset: auto 0 0 0;
    z-index: 30;
    gap: 8px;
    max-height: 76dvh;
    /* The bottom bar overlaps the sheet's foot; keep the content clear of it. */
    padding: 0 10px calc(62px + env(safe-area-inset-bottom, 0));
    overflow: hidden;
    background: #14170f;
    border-top: 1px solid var(--line);
    border-radius: 16px 16px 0 0;
    box-shadow: 0 -18px 50px rgba(0, 0, 0, .6);
    transform: translateY(101%);
    transition: transform .24s cubic-bezier(.2, .7, .3, 1);
  }
  body.sheet-open .panel { transform: none; }
  body.sheet-open .sheet-backdrop { display: block; }

  .sheet-backdrop {
    position: fixed;
    inset: 0;
    z-index: 29;
    background: rgba(0, 0, 0, .45);
  }

  .sheet-grip {
    display: block;
    flex: none;
    width: 100%;
    height: 22px;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    cursor: pointer;
  }
  .sheet-grip::before {
    content: '';
    display: block;
    width: 40px;
    height: 4px;
    margin: 9px auto 0;
    border-radius: 999px;
    background: #454c3c;
  }

  .panel-tabs { display: flex; flex: none; }
  .panel [data-panel] { display: none; }
  .panel[data-tab="play"] .controls-card,
  .panel[data-tab="analysis"] .analysis-card { display: grid; flex: 1 1 auto; overflow-y: auto; }
  .panel[data-tab="moves"] .moves-card { display: flex; flex: 1 1 auto; }
  .panel[data-tab="analysis"] .analysis-card { display: flex; flex-direction: column; }
  .lines { max-height: none; flex: 1 1 auto; }
  /* The controls scroll on a short phone, so keep the actions always reachable. */
  .controls-card .button-row {
    position: sticky;
    bottom: -1px;
    margin-bottom: -2px;
    padding: 8px 0 2px;
    background: linear-gradient(180deg, rgba(25, 28, 23, 0), var(--panel) 22%);
  }
  /* The strips beside the board already name both players. */
  .players-card { display: none; }
  .modes { margin-inline: 0; }
  .brand { display: none; }
  .badge { display: none; }
  .card { padding: 10px 11px; }
  /* Above the board rather than below it: the foot of the screen is where the
     toolbar and the bottom bar live, and a toast there covers them. */
  .toast { top: calc(84px + env(safe-area-inset-top, 0)); }
  .topbar { padding: 6px 8px; gap: 8px; }
  .topbar-right { margin-left: auto; }
  .topbar .icon-button { height: 34px; min-width: 34px; }
  .primary, .secondary, .ghost { min-height: 42px; }
  select { height: 40px; }
}

/* Short windows: buy the panel some room back from the chrome around it. */
@media (min-aspect-ratio: 1 / 1) and (max-height: 760px) {
  :root { --panel-width: clamp(224px, 34vw, 300px); }
  .card { padding: 9px 11px; }
  .panel { gap: 7px; }
  .players-card { gap: 3px; }
  .status { margin-top: 3px; padding-top: 6px; }
  .lines { max-height: 21vh; }
  .eval-graph { height: 34px; }
  .controls-card { gap: 7px; }
  .layout { gap: 9px; padding: 9px; }
}

@media (max-width: 560px) {
  .field-row { flex-direction: column; gap: 8px; }
  .field-row[data-show="engine"] { flex-direction: row; }
  .board-toolbar { gap: 5px; }
  .board-toolbar .chip-button { padding: 0 11px; }
  .mode { padding: 5px 11px; font-size: .78rem; }
  .move-strip, .player-strip { padding-inline: 8px; }
}

/* The narrowest phones: two model names will not fit on one line, and four
   dialog buttons will not either. */
@media (max-width: 380px) {
  .field-row[data-show="engine"] { flex-direction: column; }
  dialog .button-row { flex-wrap: wrap; }
  dialog .button-row > * { flex: 1 0 40%; }
}

/* Below this the move strip costs the board more width than it is worth: the
   full move list is one tap away in the sheet. */
@media (max-height: 600px) {
  .move-strip { display: none; }
}

/* Only a tall phone can afford these; a short one spends the pixels on board. */
@media (max-width: 820px) and (max-aspect-ratio: 1 / 1) and (min-height: 700px),
       (max-aspect-ratio: 4 / 5) and (min-height: 700px) {
  .engine-strip {
    display: flex;
    flex: none;
    gap: 5px;
    align-items: center;
    justify-content: center;
    height: 34px;
    padding: 0 8px;
    overflow: hidden;
  }
  .engine-strip:empty { display: none; }
  .engine-label {
    color: #6f7866;
    font-size: .62rem;
    font-weight: 700;
    letter-spacing: .1em;
  }
  .engine-chip {
    display: inline-flex;
    gap: 6px;
    align-items: center;
    padding: 6px 10px;
    border: 0;
    border-radius: 8px;
    background: var(--panel-2);
    color: var(--text);
    font-size: .8rem;
    font-weight: 700;
    cursor: pointer;
  }
  .engine-chip.best { box-shadow: inset 0 0 0 1px rgba(168, 194, 131, .5); }
  .engine-chip:disabled { opacity: .55; cursor: default; }
  .engine-value { color: var(--muted); font: 600 .68rem ui-monospace, monospace; }

}

/* A tall phone — and only a phone, where the board is capped by the screen's
   width rather than its height — has room to spare: it goes into the things a
   thumb has to hit. Anything wider is height-limited and would lose board. */
@media (max-width: 480px) and (min-height: 700px) {
  .move-strip { height: 38px; }
  .strip-move { padding: 8px 9px; }
  .player-strip { height: 40px; }
  .mode { padding: 8px 15px; }
  .board-toolbar { padding-top: 8px; }
  .board-toolbar .chip-button, .board-toolbar .icon-button, .quick-action { height: 40px; }
  .board-status { height: 22px; line-height: 22px; }
  .bar-button { min-height: 58px; }
}

/* A small phone: shave the chrome so the board can still fill the width. */
@media (max-width: 820px) and (max-aspect-ratio: 1 / 1) and (max-height: 680px),
       (max-aspect-ratio: 4 / 5) and (max-height: 680px) {
  .topbar { padding: 4px 8px; }
  .topbar .icon-button { height: 30px; min-width: 30px; }
  .mode { padding: 4px 10px; }
  .move-strip, .player-strip { height: 26px; }
  .board-status { height: 15px; line-height: 15px; }
  .board-toolbar { padding-top: 3px; }
  .board-toolbar .chip-button, .board-toolbar .icon-button { height: 30px; }
  .bar-button { min-height: 46px; }
}

/* A phone lying on its side keeps the board beside the panel (see the stacking
   query above), and every row of chrome it can lose goes to the board. */
@media (max-height: 500px) and (min-aspect-ratio: 3 / 2) {
  :root { --panel-width: clamp(224px, 30vw, 300px); --gap: 8px; }
  .topbar { padding: 3px 8px; }
  .brand, .badge { display: none; }
  .layout { padding: 6px 8px; }
  .board-area { gap: 5px; }
  .board-toolbar { gap: 5px; }
  .nav-group { padding: 2px; }
  .icon-button, .chip-button { height: 26px; }
  .card { padding: 8px 10px; }
  .panel { gap: 6px; }
  .players-card { gap: 2px; }
  .status { margin-top: 2px; padding-top: 5px; }
  .lines { max-height: 34vh; }
  .eval-graph { height: 28px; }
  .controls-card { gap: 7px; }
  .primary, .secondary, .ghost { min-height: 32px; }
  select { height: 30px; }
  input[type="range"] { height: 26px; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}
