/* ============================================================
   Layout and components
   ============================================================ */

*, *::before, *::after { box-sizing: border-box; }

html {
  /* Stops iOS inflating text of its own accord when a column is narrow,
     which reads as the page having silently zoomed itself. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

html, body {
  height: 100%;
  margin: 0;
  background: var(--ground);
  background-attachment: fixed;
  color: var(--label);
  font: var(--t-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
body { overflow: hidden; }
img { max-width: 100%; }
[hidden] { display: none !important; }

button, input, select { font: inherit; color: inherit; }

:focus-visible {
  outline: 3px solid var(--blue);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ---------- App shell ---------- */
.app {
  display: grid;
  grid-template-rows: 48px minmax(0, 1fr);
  grid-template-columns: 284px minmax(0, 1fr) 372px;
  grid-template-areas:
    "toolbar toolbar toolbar"
    "sidebar board   panel";
  height: 100dvh;
  gap: var(--s3);
  padding: 0 var(--s3) var(--s3);
}

/* ---------- Toolbar (translucent material) ---------- */
.toolbar {
  grid-area: toolbar;
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: 0 var(--s2) 0 var(--s3);
  background: transparent;
  position: relative;
  z-index: 20;
}
.toolbar h1 {
  font: var(--t-headline);
  margin: 0;
  letter-spacing: -0.01em;
}
.toolbar .spacer { flex: 1; }

.mark {
  width: 26px; height: 26px;
  border-radius: 6px;
  background: linear-gradient(160deg, var(--blue), var(--indigo));
  display: grid; place-items: center;
  color: #fff; font-size: 15px; line-height: 1;
  flex: none;
}

/* ---------- Buttons ---------- */
.btn {
  min-height: 26px;
  padding: 0 var(--s4);
  border: 0.5px solid transparent;
  border-radius: var(--r-capsule);
  background: var(--fill-tertiary);
  color: var(--label);
  font: var(--t-subhead);
  cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  transition: background var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
  white-space: nowrap;
}
.btn:hover { background: var(--fill-secondary); }
.btn:active { transform: scale(0.97); }
.btn[disabled] { opacity: .4; cursor: default; transform: none; }
.btn-primary {
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--blue) 92%, white) 0%, var(--blue) 100%);
  color: #fff; font-weight: 590;
  border-color: color-mix(in srgb, var(--blue) 70%, black);
  box-shadow: 0 1px 3px rgba(0,0,0,.20), inset 0 1px 0 rgba(255,255,255,.34);
}
.btn-primary:hover { background: var(--blue); filter: brightness(1.08); }
.btn-icon {
  width: 28px; height: 28px; padding: 0; border-radius: var(--r-capsule);
  justify-content: center; background: transparent;
  color: var(--label-secondary); font-size: 15px;
}
.btn-icon:hover { background: var(--fill-tertiary); color: var(--label); }

/* Touch targets reach 44px on coarse pointers without changing the
   visual density on a mouse-driven desktop. */
@media (pointer: coarse) {
  .btn { min-height: var(--tap); padding: 0 var(--s4); }
  .btn-icon { width: var(--tap); height: var(--tap); }
}

/* ---------- Text fields ---------- */
.field {
  width: 100%;
  min-height: 28px;
  padding: 4px var(--s3);
  border: 0.5px solid var(--separator);
  border-radius: var(--r-control);
  background: var(--bg-tertiary);
  color: var(--label);
  font: var(--t-subhead);
}
.field::placeholder { color: var(--label-tertiary); }
.field:focus { outline: none; border-color: var(--blue); box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue) 22%, transparent); }

/* ---------- Sidebar ---------- */
.sidebar {
  grid-area: sidebar;
  display: flex; flex-direction: column;
  min-height: 0;
  background: var(--material-regular);
  -webkit-backdrop-filter: var(--blur-deep);
  backdrop-filter: var(--blur-deep);
  border: 0.5px solid var(--glass-edge-soft);
  border-radius: var(--r-xl);
  box-shadow: 0 10px 34px var(--glass-ring), inset 0 1px 0 var(--glass-edge);
  overflow: hidden;
}
.sidebar-head { padding: var(--s4); display: grid; gap: var(--s2); }
.sidebar-head .row { display: flex; gap: var(--s2); }
.sidebar-head .row .field { flex: 1; }

.sidebar-scroll { overflow-y: auto; padding: 0 var(--s3) var(--s6); min-height: 0; flex: 1; }

.section-label {
  font: var(--t-footnote);
  font-weight: 590;
  color: var(--label-secondary);
  padding: var(--s3) var(--s2) var(--s2);
}

/* Inset grouped list */
.group {
  background: var(--material-thin);
  border: 0.5px solid var(--glass-edge-soft);
  border-radius: var(--r-card);
  overflow: hidden;
  box-shadow: 0 2px 10px var(--glass-ring), inset 0 1px 0 var(--glass-edge-soft);
}

.game-row {
  display: grid;
  grid-template-columns: 4px 1fr auto;
  gap: var(--s3);
  align-items: center;
  width: 100%;
  padding: var(--s3);
  background: transparent;
  border: none;
  border-bottom: 0.5px solid var(--separator);
  cursor: pointer;
  text-align: left;
  transition: background var(--dur-fast) var(--ease);
}
.game-row:last-child { border-bottom: none; }
.game-row:hover { background: var(--fill-tertiary); }
.game-row[aria-current="true"] { background: var(--blue); }
.game-row[aria-current="true"] * { color: #fff !important; }

.result-dot { width: 4px; height: 30px; border-radius: 2px; background: var(--gray); }
.result-win  { background: var(--green); }
.result-loss { background: var(--red); }
.result-draw { background: var(--gray); }

.game-main { min-width: 0; }
.game-opp {
  font: var(--t-subhead); font-weight: 590;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.game-meta {
  font: var(--t-caption); color: var(--label-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.game-side {
  font: var(--t-caption2);
  color: var(--label-secondary);
  border: 0.5px solid var(--separator);
  border-radius: 4px;
  padding: 1px 4px;
}

/* ---------- Board column ---------- */
.board-col {
  grid-area: board;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: var(--s4);
  padding: var(--s5);
  min-width: 0; min-height: 0;
  overflow: auto;
}

.board-stage {
  display: flex;
  gap: var(--s3);
  align-items: flex-start;
  width: 100%;
}

/* The stage sets the size for everything in the column: the board fills the
   width left over by the eval bar, and its aspect-ratio supplies the height. */
.stage-wrap {
  display: grid;
  gap: var(--s3);
  justify-items: center;
  width: min(58vh, 100%);
}

/* Eval bar: the one loud element */
.evalbar {
  width: 16px;
  flex: 0 0 16px;
  align-self: stretch;
  border: 0.5px solid var(--separator);
  border-radius: 8px;
  overflow: hidden;
  background: var(--piece-b);
  box-shadow: var(--shadow-1);
  position: relative;
}
.evalbar-fill {
  position: absolute; left: 0; right: 0; bottom: 0;
  background: var(--piece-w);
  height: 50%;
  transition: height var(--dur) var(--ease);
}
.evalbar-mid {
  position: absolute; left: 0; right: 0; top: 50%;
  height: 1px; background: var(--label-quaternary);
}

.board-wrap { display: grid; gap: 0; }

.board {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  grid-template-rows: repeat(8, 1fr);
  flex: 1 1 auto;
  min-width: 0;
  aspect-ratio: 1;
  border-radius: var(--r-card);
  overflow: hidden;
  box-shadow: 0 12px 40px var(--glass-ring), 0 0 0 0.5px var(--glass-edge-soft);
  user-select: none;
  container-type: inline-size;
}
.sq { position: relative; display: grid; place-items: center; }
.sq.light { background: var(--sq-light); }
.sq.dark  { background: var(--sq-dark); }
.sq.from::after, .sq.to::after, .sq.check::after {
  content: ""; position: absolute; inset: 0;
}
.sq.from::after  { background: var(--sq-from); }
.sq.to::after    { background: var(--sq-to); }
.sq.check::after { background: radial-gradient(circle, var(--sq-check) 0%, transparent 72%); }

.piece {
  position: relative; z-index: 1;
  font-size: 9.4cqw;
  line-height: 1;
  pointer-events: none;
}
.piece.w { color: var(--piece-w); text-shadow: 0 0 1px var(--piece-w-edge), 0 1px 1px rgba(0,0,0,.28); -webkit-text-stroke: 1.1px var(--piece-w-edge); }
.piece.b { color: var(--piece-b); text-shadow: 0 1px 1px rgba(0,0,0,.28); -webkit-text-stroke: 0.9px var(--piece-b-edge); }

.coord {
  position: absolute; font: var(--t-caption2); font-weight: 600;
  color: var(--label-secondary); opacity: .75; z-index: 2;
}
.coord.file { bottom: 1px; right: 3px; }
.coord.rank { top: 1px; left: 3px; }

/* Players above/below board */
.player {
  display: flex; align-items: center; gap: var(--s2);
  width: 100%; padding: 2px 2px;
  font: var(--t-subhead);
}
.player .name { font-weight: 590; }
.player .elo { color: var(--label-secondary); font: var(--t-footnote); }
.player .acc {
  margin-left: auto;
  font: var(--t-footnote); font-weight: 600;
  font-variant-numeric: tabular-nums;
  padding: 2px 7px; border-radius: 6px;
  background: var(--fill-tertiary);
}
.swatch { width: 11px; height: 11px; border-radius: 3px; border: 0.5px solid var(--separator); }
.swatch.w { background: var(--piece-w); }
.swatch.b { background: var(--piece-b); }

/* Transport controls */
.transport { display: flex; align-items: center; gap: var(--s2); }
.transport .btn-icon { width: 32px; height: 28px; background: var(--bg-tertiary); box-shadow: var(--shadow-1); }
.ply-label {
  font: var(--t-footnote); font-variant-numeric: tabular-nums;
  color: var(--label-secondary); min-width: 76px; text-align: center;
}

/* ---------- Analysis panel ---------- */
.panel {
  grid-area: panel;
  display: flex; flex-direction: column;
  min-height: 0;
  background: var(--material-regular);
  -webkit-backdrop-filter: var(--blur-deep);
  backdrop-filter: var(--blur-deep);
  border: 0.5px solid var(--glass-edge-soft);
  border-radius: var(--r-xl);
  box-shadow: 0 10px 34px var(--glass-ring), inset 0 1px 0 var(--glass-edge);
  overflow: hidden;
}
.panel-scroll { overflow-y: auto; padding: var(--s4); min-height: 0; flex: 1; display: grid; gap: var(--s4); align-content: start; }

.card {
  background: var(--material-thin);
  -webkit-backdrop-filter: saturate(150%) blur(8px);
  backdrop-filter: saturate(150%) blur(8px);
  border: 0.5px solid var(--glass-edge-soft);
  border-radius: var(--r-card);
  box-shadow: 0 2px 10px var(--glass-ring), inset 0 1px 0 var(--glass-edge-soft);
  padding: var(--s4);
}
.card h2 { font: var(--t-headline); margin: 0 0 var(--s3); }
.card h3 { font: var(--t-subhead); font-weight: 590; margin: 0 0 var(--s2); }

/* Accuracy readout */
.accuracy { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3); }
.acc-cell { text-align: center; }
.acc-val {
  font: 700 22px/26px var(--font);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.acc-cap { font: var(--t-caption); color: var(--label-secondary); }

/* Eval graph */
.graph { width: 100%; height: 72px; display: block; border-radius: var(--r-control); background: var(--fill-tertiary); cursor: crosshair; }

/* Move list */
.moves {
  display: grid;
  grid-template-columns: 34px 1fr 1fr;
  gap: 2px 4px;
  align-items: stretch;
  max-height: 42dvh;
  overflow-y: auto;
  scrollbar-width: thin;
  overscroll-behavior: contain;
}
.move-num {
  font: var(--t-footnote); font-variant-numeric: tabular-nums;
  color: var(--label-tertiary); display: grid; place-items: center;
}
.move {
  display: flex; align-items: center; gap: 5px;
  padding: 4px 7px; border: none; background: transparent;
  border-radius: 6px; cursor: pointer; text-align: left;
  font: var(--t-subhead); font-variant-numeric: tabular-nums;
  transition: background var(--dur-fast) var(--ease);
}
.move:hover { background: var(--fill-tertiary); }
.move[aria-current="true"] { background: var(--blue); color: #fff; font-weight: 600; }
.move .san { font-family: var(--font-mono); font-size: 11px; }
.move .glyph { font-size: 11px; line-height: 1; }

/* Quality glyph + color pairing */
.q-brilliant  { color: var(--q-brilliant); }
.q-great      { color: var(--q-great); }
.q-best       { color: var(--q-best); }
.q-good       { color: var(--label-secondary); }
.q-book       { color: var(--q-book); }
.q-inaccuracy { color: var(--q-inaccuracy); }
.q-mistake    { color: var(--q-mistake); }
.q-blunder    { color: var(--q-blunder); }
.move[aria-current="true"] .glyph { color: #fff; }

/* Quality summary rows */
.tally { display: grid; gap: 2px; }
.tally-row {
  display: grid; grid-template-columns: 18px 1fr auto auto;
  gap: var(--s2); align-items: center;
  font: var(--t-subhead); padding: 3px 0;
}
.tally-row .n { font-variant-numeric: tabular-nums; font-weight: 600; min-width: 22px; text-align: right; }
.tally-row .n.b { color: var(--label-secondary); }

/* Current-move detail */
.detail-eval {
  font: 700 17px/22px var(--font-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.detail-line {
  font: var(--t-caption); font-family: var(--font-mono);
  color: var(--label-secondary); word-break: break-word;
  margin-top: var(--s2);
}
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px; border-radius: 999px;
  font: var(--t-footnote); font-weight: 600;
  background: var(--fill-tertiary);
}

/* Coach */
.coach-body { font: var(--t-body-loose); white-space: pre-wrap; }
.coach-body:empty::before { content: "Run the analysis, then ask the coach to talk through what changed."; color: var(--label-tertiary); }

/* Progress */
.progress { height: 4px; border-radius: 2px; background: var(--fill-tertiary); overflow: hidden; }
.progress > i { display: block; height: 100%; background: var(--blue); width: 0; transition: width 120ms linear; }

/* Empty / status states */
.empty {
  display: grid; place-items: center; gap: var(--s2);
  text-align: center; padding: var(--s10) var(--s5);
  color: var(--label-secondary);
}
.empty .big { font-size: 36px; opacity: .5; }
.empty p { margin: 0; font: var(--t-subhead); max-width: 34ch; }

.status { font: var(--t-footnote); color: var(--label-secondary); }
.status.err { color: var(--red); }

/* Spinner */
.spin {
  width: 14px; height: 14px; flex: none;
  border: 2px solid var(--fill); border-top-color: var(--blue);
  border-radius: 50%; animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* Settings popover */
.popover {
  position: absolute; top: 46px; right: var(--s4);
  width: 320px; padding: var(--s4);
  background: var(--material-thick);
  -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur);
  border: 0.5px solid var(--glass-edge-soft);
  border-radius: var(--r-large);
  box-shadow: 0 20px 60px var(--glass-ring), inset 0 1px 0 var(--glass-edge);
  /* Above the phone tab bar (45) and the sticky nav bar (40): a panel that
     opens over the page must not be the thing that ends up underneath it. */
  z-index: 100;
  display: grid; gap: var(--s3);
  /* However tall the panel grows, it scrolls rather than running off the
     screen, so every control in it stays reachable. */
  max-height: calc(100dvh - 60px);
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.popover label { font: var(--t-footnote); font-weight: 590; display: grid; gap: 5px; }
.popover .hint { font: var(--t-caption); color: var(--label-secondary); font-weight: 400; }
.popover a { color: var(--blue); }

/* Catches the tap that lands outside the panel. Transparent on a desktop,
   where the popover reads as attached to the gear; dimmed once it is a
   sheet, where it reads as a layer over the page. */
.sheet-scrim { position: fixed; inset: 0; z-index: 90; background: transparent; }

/* The sheet header is built by scripts/sheet.js and shown only in sheet mode,
   so the desktop popover keeps the shape it had. */
.sheet-head { display: none; }

/* ---------- Responsive ---------- */
@media (max-width: 1180px) {
  .app {
    grid-template-columns: 264px minmax(0, 1fr);
    grid-template-areas: "toolbar toolbar" "sidebar board" "sidebar panel";
    grid-template-rows: 48px minmax(0, 1fr) minmax(0, 46dvh);
  }
  .stage-wrap { width: min(40vh, 100%); }
}

/* The tab bar is a phone affordance only; the phone block turns it on. */
.tabbar { display: none; }

/* ============================================================
   Phone layout: iOS patterns
   A navigation bar pinned to the top, a tab bar pinned to the bottom, and
   grouped lists between them. Both bars are glass and sit inside the safe
   area, so nothing hides under the notch or the home indicator.
   ============================================================ */
@media (max-width: 760px) {
  body { overflow: auto; background: var(--bg-grouped); }

  .app {
    display: flex;
    flex-direction: column;
    height: auto;
    gap: 0;
    padding: 0;
    /* room for the two fixed bars */
    padding-bottom: calc(52px + env(safe-area-inset-bottom, 0px));
  }
  /* The game comes first on a phone; settings sit below it, not above. */
  .toolbar   { order: 0; }
  .board-col { order: 1; }
  .panel     { order: 2; }
  .sidebar   { order: 3; }

  /* ---- Navigation bar ---- */
  .toolbar {
    position: sticky;
    top: 0;
    z-index: 40;
    height: auto;
    min-height: 44px;
    padding: calc(env(safe-area-inset-top, 0px) + 6px) var(--s2) 6px;
    gap: var(--s2);
    background: var(--material-thick);
    -webkit-backdrop-filter: var(--blur);
    backdrop-filter: var(--blur);
    border-bottom: 0.5px solid var(--separator);
    border-radius: 0;
  }
  .toolbar h1 { font: var(--t-headline); }
  /* The mode switch moves to the tab bar on a phone, and the tab bar already
     names the section, so the mark, and on Play the title too, give their
     space to the actions. */
  .toolbar .segmented { display: none; }
  .mark { display: none; }
  body[data-page="play"] .toolbar h1 { display: none; }
  /* On the board pages the wordmark had to share the bar with a primary
     action and two icons, and at 375px it wrapped onto a second line and
     doubled the height of the bar. The tab bar already names the section, so
     the mark carries the brand and the words step aside. Home and the
     document pages have the room, and keep theirs. */
  body:not([data-page="home"]):not([data-page="doc"]) .mark { display: grid; }
  body:not([data-page="home"]):not([data-page="doc"]) .toolbar h1 { display: none; }
  .toolbar h1 { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .toolbar .brand { min-width: 0; }

  /* ---- Tab bar ---- */
  .tabbar {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 45;
    display: flex;
    padding-bottom: env(safe-area-inset-bottom, 0px);
    background: var(--material-thick);
    -webkit-backdrop-filter: var(--blur);
    backdrop-filter: var(--blur);
    border-top: 0.5px solid var(--separator);
  }
  .tabbar a {
    flex: 1;
    min-height: 50px;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    gap: 2px;
    text-decoration: none;
    color: var(--label-secondary);
    font: var(--t-caption2);
  }
  .tabbar a[aria-current="page"] { color: var(--blue); }
  .tabbar .tab-glyph { font-size: 20px; line-height: 1; }

  /* ---- Panes become plain sections ---- */
  .sidebar, .panel {
    background: transparent;
    -webkit-backdrop-filter: none; backdrop-filter: none;
    border: none;
    border-radius: 0;
    box-shadow: none;
    overflow: visible;
  }
  .sidebar-scroll, .panel-scroll {
    overflow: visible;
    max-height: none;
    padding: var(--s3) var(--inset) var(--s5);
  }
  .moves { max-height: none; overflow: visible; }

  /* ---- Inset grouped lists ---- */
  .group {
    background: var(--bg-elevated);
    border: none;
    border-radius: 10px;
    box-shadow: none;
  }
  .game-row, .level-row { min-height: var(--row-min); padding: 11px var(--s4); }
  .game-row { grid-template-columns: 4px 1fr auto; }
  .section-label {
    font: var(--t-footnote);
    text-transform: none;
    padding: var(--s5) var(--s1) var(--s2);
  }

  .card {
    background: var(--bg-elevated);
    -webkit-backdrop-filter: none; backdrop-filter: none;
    border: none;
    border-radius: 10px;
    box-shadow: none;
    padding: var(--s4);
  }

  /* ---- Board ---- */
  .board-col { padding: var(--s4) var(--inset) var(--s5); }
  .stage-wrap { width: 100%; }
  .board { border-radius: 10px; }
  .piece { font-size: 9.6cqw; }

  /* ---- Controls reach the 44pt target ---- */
  .btn { min-height: var(--tap); padding: 0 var(--s5); font: var(--t-body); }
  .btn-icon { width: var(--tap); height: var(--tap); }
  .transport .btn-icon { width: var(--tap); height: var(--tap); }
  .field { min-height: var(--tap); font: var(--t-body); }
  .move { min-height: 34px; }
  .segmented.wide button { min-height: var(--tap); }

  .sidebar-head { padding: var(--s3) var(--inset); }
  .toolbar .spacer { flex: 1; }

  /* ---- Navigation stack ----
     A phone shows one screen at a time: the list of games, or the game.
     Choosing a game pushes; the back button pops. */
  body[data-view="list"] .board-col,
  body[data-view="list"] .panel { display: none; }
  body[data-view="detail"] .sidebar { display: none; }
  body[data-view="detail"] #backBtn { display: inline-flex; }
  /* The back button takes the leading slot the mark held. */
  body[data-view="detail"] .toolbar h1,
  body[data-view="detail"] .mark { display: none; }
}

#backBtn { display: none; }

/* ============================================================
   Settings as a sheet
   A phone width, or any window too short to hold the panel — a phone held
   sideways is both wide and short, which is where the old popover ran off
   the bottom of the screen with its Done button on it. The sheet fixes the
   panel to the bottom edge, scrolls its own contents, and pins a header with
   a close button to the top of that scroll, so the way out is on screen from
   the first frame whatever the panel contains.
   ============================================================ */
@media (max-width: 760px), (max-height: 620px) {
  .popover {
    position: fixed;
    top: auto; right: 0; left: 0;
    bottom: 0;
    width: auto;
    max-width: 560px;
    margin-inline: auto;
    /* Leaves the page visible above the sheet, so it reads as a layer. */
    max-height: min(86dvh, 100dvh - 44px);
    padding: 0 var(--inset) calc(var(--s5) + env(safe-area-inset-bottom, 0px));
    border: none;
    border-radius: var(--r-large) var(--r-large) 0 0;
    /* Opaque: a sheet sits over a dimmed page, and a second blur layer on
       top of the first only muddies it. */
    background: var(--bg-elevated);
    -webkit-backdrop-filter: none; backdrop-filter: none;
    box-shadow: 0 -12px 44px rgba(0, 0, 0, 0.38);
  }

  .sheet-scrim {
    background: rgba(0, 0, 0, 0.4);
    -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  }
  /* The page must not scroll under an open sheet; the sheet has its own. */
  body.sheet-open { overflow: hidden; }

  .sheet-head {
    display: flex;
    align-items: center;
    gap: var(--s2);
    position: sticky;
    top: 0;
    z-index: 2;
    /* Spans the sheet's padding so scrolled content passes behind it. */
    margin: 0 calc(-1 * var(--inset)) var(--s2);
    padding: var(--s3) var(--s2) var(--s3) var(--inset);
    background: var(--bg-elevated);
    border-bottom: 0.5px solid var(--separator);
  }
  .sheet-title { flex: 1; font: var(--t-headline); }
  .sheet-close {
    flex: none;
    background: var(--fill-tertiary);
    color: var(--label-secondary);
    font-size: 15px;
  }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* Report stack */
.report { display: grid; gap: var(--s4); }

/* Cross-check against chess.com's own number, when it has one */
.compare { margin: var(--s2) 0 0; line-height: 1.45; }

/* ---------- Interactive board ---------- */
.sq.selected::before {
  content: ""; position: absolute; inset: 0;
  background: var(--sq-to); z-index: 0;
}
.board[data-input="on"] .sq { cursor: pointer; }
.target {
  position: absolute; z-index: 2; pointer-events: none;
  width: 30%; height: 30%; border-radius: 50%;
  background: rgba(20, 24, 28, 0.32);
}
.target.capture {
  width: 88%; height: 88%; border-radius: 50%;
  background: transparent;
  border: 5px solid rgba(20, 24, 28, 0.30);
  box-sizing: border-box;
}
:root[data-theme="dark"] .target,
:root[data-theme="dark"] .target.capture { background: rgba(255,255,255,.26); }
:root[data-theme="dark"] .target.capture { background: transparent; border-color: rgba(255,255,255,.28); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .target { background: rgba(255,255,255,.26); }
  :root:not([data-theme="light"]) .target.capture { background: transparent; border-color: rgba(255,255,255,.28); }
}

/* ---------- Segmented control ---------- */
.segmented {
  display: inline-flex;
  padding: 3px;
  gap: 2px;
  background: var(--fill-tertiary);
  border: 0.5px solid var(--glass-edge-soft);
  border-radius: var(--r-capsule);
}
.segmented a, .segmented button {
  appearance: none; border: none; background: transparent;
  padding: 3px 12px; border-radius: var(--r-capsule);
  font: var(--t-subhead); font-weight: 500;
  color: var(--label); text-decoration: none; cursor: pointer;
  transition: background var(--dur-fast) var(--ease);
}
.segmented a[aria-current="page"], .segmented button[aria-checked="true"] {
  background: var(--bg-tertiary);
  box-shadow: var(--shadow-1);
  font-weight: 590;
}
.segmented.wide { display: flex; }
.segmented.wide button { flex: 1; text-align: center; }

/* ---------- Level ladder ---------- */
.level-row {
  display: grid; grid-template-columns: 52px 1fr; gap: var(--s3);
  align-items: center; width: 100%;
  padding: var(--s3); background: transparent; border: none;
  border-bottom: 0.5px solid var(--separator);
  cursor: pointer; text-align: left;
  transition: background var(--dur-fast) var(--ease);
}
.level-row:last-child { border-bottom: none; }
.level-row:hover { background: var(--fill-tertiary); }
.level-row[aria-checked="true"] { background: var(--blue); }
.level-row[aria-checked="true"] * { color: #fff !important; }
.level-elo {
  font: 700 13px/1 var(--font); font-variant-numeric: tabular-nums;
  text-align: right; color: var(--label);
}
.level-name { font: var(--t-subhead); font-weight: 590; }
.level-blurb { font: var(--t-caption); color: var(--label-secondary); }

/* ---------- Promotion picker ---------- */
.promo {
  display: flex; align-items: center; gap: var(--s2);
  padding: var(--s3); border-radius: var(--r-card);
  background: var(--material-thick);
  -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur);
  border: 0.5px solid var(--separator);
  box-shadow: var(--shadow-2);
  font: var(--t-subhead);
}
/* On a phone the four choices laid out in one row measured wider than the
   screen, so Bishop and Knight were off the edge of it. They wrap into a
   grid, and the picker floats clear of the tab bar rather than sitting below
   the board where a scrolled page can hide it: a promotion has to be
   answered before the game continues. */
@media (max-width: 760px) {
  .promo {
    position: fixed;
    z-index: 60;
    left: var(--inset); right: var(--inset);
    bottom: calc(52px + env(safe-area-inset-bottom, 0px) + var(--s3));
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--s2);
    background: var(--bg-elevated);
    box-shadow: 0 14px 44px rgba(0, 0, 0, 0.42);
  }
  .promo > span { grid-column: 1 / -1; text-align: center; }
  .promo .btn { justify-content: center; padding: 0 var(--s3); }
}

/* ---------- Turn / thinking ---------- */
.turn-dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--green); display: inline-block; margin-right: 6px;
}
.hint { font: var(--t-caption); color: var(--label-secondary); margin: 0; }

/* Dragged piece follows the pointer */
.piece.ghost {
  position: fixed;
  z-index: 100;
  transform: translate(-50%, -50%);
  pointer-events: none;
  opacity: 0.92;
  filter: drop-shadow(0 6px 10px rgba(0,0,0,.35));
}
.board { touch-action: none; }

/* ---------- Scrollbars ----------
   The default macOS overlay scrollbar renders as a heavy opaque bar inside
   these panels. Make it thin and quiet, and let it fade with the surface. */
.sidebar-scroll, .panel-scroll, .moves {
  scrollbar-width: thin;
  scrollbar-color: var(--label-quaternary) transparent;
}
.sidebar-scroll::-webkit-scrollbar,
.panel-scroll::-webkit-scrollbar,
.moves::-webkit-scrollbar { width: 8px; height: 8px; }
.sidebar-scroll::-webkit-scrollbar-track,
.panel-scroll::-webkit-scrollbar-track,
.moves::-webkit-scrollbar-track { background: transparent; }
.sidebar-scroll::-webkit-scrollbar-thumb,
.panel-scroll::-webkit-scrollbar-thumb,
.moves::-webkit-scrollbar-thumb {
  background: var(--label-quaternary);
  border-radius: 4px;
  border: 2px solid transparent;
  background-clip: content-box;
}
.sidebar-scroll:hover::-webkit-scrollbar-thumb,
.panel-scroll:hover::-webkit-scrollbar-thumb,
.moves:hover::-webkit-scrollbar-thumb { background: var(--label-tertiary); background-clip: content-box; }

/* ---------- SVG piece sets ---------- */
.piece.svg {
  width: 88%;
  height: 88%;
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  -webkit-text-stroke: 0;
  text-shadow: none;
  filter: drop-shadow(0 1px 1px rgba(0,0,0,.22));
}
.piece.svg.ghost { filter: drop-shadow(0 6px 10px rgba(0,0,0,.35)); }

/* ---------- Theme picker ---------- */
.picker-title { font: var(--t-footnote); font-weight: 590; color: var(--label-secondary); margin: var(--s2) 0 var(--s1); }
.picker-row { display: flex; flex-wrap: wrap; gap: var(--s2); }
.swatch-board, .swatch-piece {
  width: 40px; height: 40px; padding: 0;
  border: 2px solid transparent; border-radius: 10px;
  background: var(--fill-tertiary); cursor: pointer;
  display: grid; place-items: center; overflow: hidden;
  transition: transform var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.swatch-board {
  background:
    linear-gradient(90deg, var(--a) 50%, var(--b) 50%) top / 100% 50% no-repeat,
    linear-gradient(90deg, var(--b) 50%, var(--a) 50%) bottom / 100% 50% no-repeat;
  box-shadow: inset 0 0 0 0.5px var(--separator);
}
.swatch-board:hover, .swatch-piece:hover { transform: scale(1.06); }
.swatch-board[aria-pressed="true"], .swatch-piece[aria-pressed="true"] {
  border-color: var(--blue);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue) 25%, transparent);
}
.swatch-piece img { width: 28px; height: 28px; display: block; }
.swatch-piece .piece { line-height: 1; }
@media (pointer: coarse) { .swatch-board, .swatch-piece { width: var(--tap); height: var(--tap); } }

/* ---------- Puzzles ---------- */
.puzzle-prompt {
  display: flex; align-items: center; gap: var(--s3);
  font: var(--t-headline); padding: var(--s2) var(--s1);
}
.puzzle-prompt .swatch { width: 14px; height: 14px; }
.puzzle-actions { display: flex; gap: var(--s2); flex-wrap: wrap; justify-content: center; }
.puzzle-feedback {
  font: var(--t-title3); text-align: center; min-height: 26px;
  transition: color var(--dur) var(--ease);
}
.puzzle-feedback.ok { color: var(--green); }
.puzzle-feedback.bad { color: var(--red); }
.stat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s3); text-align: center; }
.stat-val { font: 700 22px/26px var(--font); font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.stat-cap { font: var(--t-caption); color: var(--label-secondary); }
.chip-row { display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
  font: var(--t-caption); padding: 3px 9px; border-radius: 999px;
  background: var(--fill-tertiary); color: var(--label-secondary);
  border: none; cursor: pointer;
}
.chip[aria-pressed="true"] { background: var(--blue); color: #fff; }
.history { display: grid; gap: 2px; }
.history-row {
  display: grid; grid-template-columns: 18px 1fr auto; gap: var(--s2);
  align-items: center; font: var(--t-subhead); padding: 4px 0;
  border-bottom: 0.5px solid var(--separator);
}
.history-row:last-child { border-bottom: none; }
.history-row .r { font-variant-numeric: tabular-nums; color: var(--label-secondary); }
.sq.hint::after { content: ""; position: absolute; inset: 0; background: color-mix(in srgb, var(--blue) 45%, transparent); }
.sq.wrong::after { content: ""; position: absolute; inset: 0; background: color-mix(in srgb, var(--red) 45%, transparent); }
.sq.right::after { content: ""; position: absolute; inset: 0; background: color-mix(in srgb, var(--green) 45%, transparent); }

/* ---------- Insights ---------- */
.insight-bars { display: grid; gap: 6px; }
.insight-bar { display: grid; grid-template-columns: 96px 1fr 44px; gap: var(--s2); align-items: center; font: var(--t-subhead); }
.insight-bar .track { height: 8px; border-radius: 4px; background: var(--fill-tertiary); overflow: hidden; }
.insight-bar .fill { height: 100%; border-radius: 4px; background: var(--blue); }
.insight-bar .n { font-variant-numeric: tabular-nums; text-align: right; color: var(--label-secondary); }
.spark { width: 100%; height: 44px; display: block; }

/* ---------- Clocks and time controls ---------- */
.tc-group { display: grid; gap: var(--s2); }
.tc-cat { font: var(--t-caption2); color: var(--label-secondary); margin-top: var(--s1); }
.tc-row { display: flex; flex-wrap: wrap; gap: 6px; }
.clock {
  margin-left: auto;
  font: 600 15px/1 var(--font-mono);
  font-variant-numeric: tabular-nums;
  padding: 5px 10px; border-radius: 8px;
  background: var(--fill-tertiary);
  color: var(--label-secondary);
  min-width: 64px; text-align: center;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.clock.running { background: var(--label); color: var(--bg); }
.clock.low { background: var(--red); color: #fff; }
.player .acc + .clock, .player .clock { flex: none; }
@media (max-width: 760px) { .clock { font-size: 17px; padding: 6px 12px; } }

/* Vision drill hides the edge labels; reading them is the habit to break. */
.board.no-coords .coord { display: none; }

/* ---------- Arrow layer ---------- */
.board { position: relative; }
.board .arrows {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none; z-index: 3; overflow: visible;
}
.piece { will-change: transform; }

/* ---------- Leaderboard ---------- */
.lb { display: grid; gap: 1px; margin-top: var(--s2); }
.lb-row {
  display: grid; grid-template-columns: 36px 28px 1fr auto 64px; gap: var(--s3);
  align-items: center; padding: 6px 4px; border-radius: 8px;
  text-decoration: none; color: inherit; font: var(--t-subhead);
  border-bottom: 0.5px solid var(--separator);
}
.lb-row:hover { background: var(--fill-tertiary); }
.lb-row.me { background: color-mix(in srgb, var(--blue) 14%, transparent); font-weight: 600; }
.lb-rank { font-variant-numeric: tabular-nums; color: var(--label-secondary); text-align: right; }
.lb-avatar { width: 28px; height: 28px; border-radius: 6px; object-fit: cover; background: var(--fill-tertiary); }
.lb-name { display: flex; align-items: center; gap: 6px; min-width: 0; overflow: hidden; white-space: nowrap; }
.lb-user { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.lb-title { flex: none; font: var(--t-caption2); color: #fff; background: var(--red); padding: 1px 5px; border-radius: 4px; }
.lb-flag { flex: none; font-size: 14px; }
.lb-wl { font: var(--t-caption); color: var(--label-tertiary); font-variant-numeric: tabular-nums; }
.lb-score { font-weight: 700; font-variant-numeric: tabular-nums; text-align: right; }
/* On a phone the win–loss record goes, and the fixed columns and gaps are
   pulled in as far as they will go, because every pixel they give back is a
   pixel of username that fits before the ellipsis. */
@media (max-width: 760px) {
  .lb-row { grid-template-columns: 22px 24px 1fr 50px; gap: var(--s2); padding: 6px 2px; }
  .lb-wl { display: none; }
}

/* ---------- Solo Chess move budget ---------- */
.sq.solo-1::before {
  content: ""; position: absolute; top: 4px; right: 4px; width: 7px; height: 7px;
  border-radius: 50%; background: var(--orange); z-index: 2; box-shadow: 0 0 0 1.5px var(--bg);
}
.sq.solo-0 .piece { opacity: 0.38; filter: grayscale(1); }

/* ---------- Result alert ---------- */
.result-backdrop {
  position: fixed; inset: 0; z-index: 200;
  display: grid; place-items: center;
  padding: var(--s5);
  background: rgba(0, 0, 0, 0.28);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  backdrop-filter: blur(14px) saturate(140%);
  opacity: 0;
  transition: opacity 180ms var(--ease);
}
.result-backdrop.show { opacity: 1; }
.result-card {
  width: min(360px, 100%);
  /* A long reason line, or a short landscape window, must not push the
     buttons off the bottom; the card scrolls instead. */
  max-height: calc(100dvh - 2 * var(--s5));
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--s6) var(--s5) var(--s5);
  text-align: center;
  background: var(--material-thick);
  -webkit-backdrop-filter: var(--blur-deep); backdrop-filter: var(--blur-deep);
  border: 0.5px solid var(--glass-edge-soft);
  border-radius: var(--r-xl);
  box-shadow: 0 30px 90px rgba(0,0,0,.35), inset 0 1px 0 var(--glass-edge);
  opacity: 0; transform: translateY(14px) scale(0.92);
}
.result-card.in {
  animation: result-in 420ms cubic-bezier(0.34, 1.45, 0.64, 1) forwards;
}
@keyframes result-in {
  from { opacity: 0; transform: translateY(14px) scale(0.92); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
.result-glyph {
  width: 64px; height: 64px; margin: 0 auto var(--s4);
  border-radius: 50%; display: grid; place-items: center;
  font: 700 30px/1 var(--font); color: #fff;
  background: var(--blue);
  box-shadow: 0 8px 24px color-mix(in srgb, var(--blue) 45%, transparent);
  animation: glyph-pop 520ms cubic-bezier(0.34, 1.56, 0.64, 1) 80ms both;
}
@keyframes glyph-pop {
  from { transform: scale(0.4); opacity: 0; }
  60%  { transform: scale(1.12); opacity: 1; }
  to   { transform: scale(1); opacity: 1; }
}
.result-card[data-tone="win"]  .result-glyph { background: var(--green);  box-shadow: 0 8px 24px color-mix(in srgb, var(--green) 45%, transparent); }
.result-card[data-tone="loss"] .result-glyph { background: var(--red);    box-shadow: 0 8px 24px color-mix(in srgb, var(--red) 45%, transparent); }
.result-card[data-tone="draw"] .result-glyph { background: var(--gray);   box-shadow: 0 8px 24px color-mix(in srgb, var(--gray) 45%, transparent); }
.result-title  { font: var(--t-title2); margin: 0 0 var(--s2); letter-spacing: -0.01em; }
.result-detail { font: var(--t-body-loose); color: var(--label-secondary); margin: 0 0 var(--s5); }
.result-actions { display: flex; gap: var(--s2); justify-content: center; flex-wrap: wrap; }
.result-actions .btn { min-width: 120px; justify-content: center; }
@media (max-width: 760px) {
  .result-backdrop { align-items: end; padding-bottom: calc(var(--s5) + env(safe-area-inset-bottom, 0px)); }
  .result-card { width: 100%; }
  .result-title { font: var(--t-title1); }
}
/* A phone held sideways has room for the card but not for its ceremony. */
@media (max-height: 460px) {
  .result-card { padding: var(--s4) var(--s5); }
  .result-glyph { width: 40px; height: 40px; margin-bottom: var(--s2); font-size: 20px; }
  .result-detail { margin-bottom: var(--s3); }
}

/* ---------- Credit row ---------- */
.credit {
  margin-top: var(--s5); padding: var(--s3) var(--s2) var(--s2);
  border-top: 0.5px solid var(--separator);
  display: grid; gap: var(--s2);
}
.credit-by { font: var(--t-caption); color: var(--label-secondary); }
.credit-by a { color: var(--label); text-decoration: none; font-weight: 590; }
.credit-links { display: flex; flex-wrap: wrap; gap: 6px; }
.credit-link {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 9px; border-radius: 999px; border: none;
  font: var(--t-caption); font-weight: 500;
  color: var(--label-secondary); background: var(--fill-tertiary);
  text-decoration: none; cursor: pointer;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.credit-link:hover { background: var(--fill-secondary); color: var(--label); }
.credit-link.sponsor { color: var(--pink); }
.credit-link.sponsor:hover { background: color-mix(in srgb, var(--pink) 14%, transparent); color: var(--pink); }
.result-share { color: var(--label-secondary); }
@media (pointer: coarse) { .credit-link { min-height: 36px; padding: 6px 12px; font: var(--t-footnote); } }

/* ---------- Document pages (About, Privacy) ---------- */
.app.doc { grid-template-columns: 1fr; grid-template-areas: "toolbar" "board"; }
.doc-col { justify-content: flex-start; align-items: center; overflow-y: auto; }
.doc-card {
  width: 100%; max-width: 72ch;
  padding: var(--s8) var(--s8) var(--s6);
  background: var(--material-regular);
  -webkit-backdrop-filter: var(--blur-deep); backdrop-filter: var(--blur-deep);
  border: 0.5px solid var(--glass-edge-soft); border-radius: var(--r-xl);
  box-shadow: 0 10px 34px var(--glass-ring), inset 0 1px 0 var(--glass-edge);
}
.doc-kicker { font: var(--t-footnote); font-weight: 590; color: var(--blue); margin: 0 0 var(--s2); }
.doc-card h1 { font: var(--t-large-title); margin: 0 0 var(--s3); letter-spacing: -0.02em; }
.doc-card h2 { font: var(--t-title3); margin: var(--s6) 0 var(--s2); }
.doc-card p { font: var(--t-body-loose); margin: 0 0 var(--s3); max-width: 68ch; }
.doc-lede { color: var(--label-secondary); font-size: 1.06em; }
.doc-card a { color: var(--blue); text-decoration: none; }
.doc-card a:hover { text-decoration: underline; }
.doc-foot { margin-top: var(--s6); padding-top: var(--s4); border-top: 0.5px solid var(--separator); color: var(--label-secondary); }
@media (max-width: 760px) {
  .doc-card { padding: var(--s5) var(--inset); border-radius: 0; border: none; box-shadow: none; background: transparent; -webkit-backdrop-filter: none; backdrop-filter: none; }
  .doc-card h1 { font: var(--t-title1); }
}
.credit-legal { font: var(--t-caption); color: var(--label-tertiary); }
.credit-legal a { color: var(--label-secondary); text-decoration: none; }
.credit-legal a:hover { color: var(--label); }

/* ---------- Sponsor board ---------- */
.sp-row {
  display: grid; grid-template-columns: 34px 40px 1fr auto; gap: var(--s3); align-items: center;
  padding: 10px 12px; border-radius: 12px; text-decoration: none; color: inherit;
  border: 0.5px solid transparent;
  transition: background var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.sp-row:hover { background: var(--fill-tertiary); transform: translateX(2px); }
.sp-rank { font: 700 13px/1 var(--font); font-variant-numeric: tabular-nums; color: var(--label-tertiary); text-align: right; }
.sp-top .sp-rank { color: var(--label); }
.sp-rank-1 { background: color-mix(in srgb, #E6B400 12%, transparent); border-color: color-mix(in srgb, #E6B400 40%, transparent); }
.sp-rank-2 { background: color-mix(in srgb, #9AA3AD 12%, transparent); border-color: color-mix(in srgb, #9AA3AD 40%, transparent); }
.sp-rank-3 { background: color-mix(in srgb, #B87333 12%, transparent); border-color: color-mix(in srgb, #B87333 40%, transparent); }
.sp-avatar { width: 40px; height: 40px; border-radius: 10px; object-fit: cover; background: var(--fill-tertiary); display: grid; place-items: center; flex: none; }
.sp-initials { font: 700 14px/1 var(--font); color: #fff; background: hsl(var(--h, 210) 60% 48%); }
.sp-empty { border: 1.5px dashed var(--separator-opaque); color: var(--label-tertiary); font: 500 20px/1 var(--font); background: transparent; }
.sp-main { display: grid; gap: 2px; min-width: 0; }
.sp-name { font: var(--t-subhead); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sp-meta { font: var(--t-caption); color: var(--label-secondary); }
.sp-msg { font: var(--t-caption); color: var(--label-secondary); font-style: italic; }
.sp-amount { font: 700 15px/1 var(--font); font-variant-numeric: tabular-nums; color: var(--label); }
.sp-free { border: 1px dashed var(--separator-opaque); }
.sp-free .sp-name { color: var(--label-secondary); font-weight: 500; }
.sp-claim { color: var(--blue); font-weight: 600; font-size: 13px; }
.sp-rail { display: grid; gap: 4px; }

/* Compact strip in app sidebars */
.sp-strip {
  display: grid; grid-template-columns: auto 1fr auto; gap: var(--s2); align-items: center;
  margin-top: var(--s4); padding: 8px 10px; border-radius: 12px;
  background: var(--material-thin); border: 0.5px solid var(--glass-edge-soft);
  text-decoration: none; color: inherit; font: var(--t-caption);
}
.sp-strip:hover { background: var(--fill-tertiary); }
.sp-faces { display: flex; }
.sp-faces .sp-avatar { width: 22px; height: 22px; border-radius: 6px; margin-right: -6px; box-shadow: 0 0 0 2px var(--bg-tertiary); font-size: 9px; }
.sp-faces .sp-empty { font-size: 14px; }
.sp-strip-text strong { display: block; font: var(--t-footnote); font-weight: 600; color: var(--label); }
.sp-strip-text span { color: var(--label-secondary); }
.sp-chev { color: var(--label-tertiary); font-size: 16px; }

/* ---------- Home ---------- */
.brand { display: inline-flex; align-items: center; gap: var(--s3); text-decoration: none; color: inherit; }
.home-col { display: grid; gap: var(--s8); align-content: start; padding: var(--s8) var(--s6) var(--s10); max-width: 1240px; width: 100%; margin: 0 auto; }
.hero { text-align: center; max-width: 60ch; margin: var(--s6) auto 0; display: grid; gap: var(--s4); justify-items: center; }
.hero-title { font: 700 44px/1.08 var(--font); letter-spacing: -0.03em; margin: 0; }
.hero-lede { font: var(--t-body-loose); font-size: 16px; color: var(--label-secondary); margin: 0; max-width: 54ch; }
.hero-cta { display: flex; gap: var(--s2); flex-wrap: wrap; justify-content: center; }
.hero-cta .btn { min-height: 36px; padding: 0 var(--s5); font-size: 14px; }
.hero-facts { font: var(--t-caption); color: var(--label-tertiary); margin: 0; }
.home-grid { display: grid; grid-template-columns: 300px minmax(0, 1fr) 300px; gap: var(--s5); align-items: start; }
.rail { display: grid; gap: var(--s3); padding: var(--s4); background: var(--material-regular); -webkit-backdrop-filter: var(--blur-deep); backdrop-filter: var(--blur-deep); border: 0.5px solid var(--glass-edge-soft); border-radius: var(--r-xl); box-shadow: 0 10px 34px var(--glass-ring), inset 0 1px 0 var(--glass-edge); }
.rail-head h2 { font: var(--t-headline); margin: 0 0 4px; }
.rail-head .hint { margin: 0; }
/* The one button whose label grows with the sponsor count. Buttons do not
   wrap by default, and on a 320px screen "Sponsor on GitHub and claim #1"
   held on one line was pushing the whole page wider than the phone. */
.sp-cta {
  justify-content: center;
  white-space: normal;
  text-align: center;
  line-height: 1.3;
  padding: var(--s2) var(--s4);
}
.features { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); }
.feature { display: grid; gap: 6px; padding: var(--s4); border-radius: var(--r-card); text-decoration: none; color: inherit; background: var(--material-thin); border: 0.5px solid var(--glass-edge-soft); box-shadow: 0 2px 10px var(--glass-ring), inset 0 1px 0 var(--glass-edge-soft); transition: transform var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease); }
.feature:hover { transform: translateY(-2px); background: var(--material-regular); }
.f-glyph { font-size: 26px; line-height: 1; color: var(--blue); }
.f-title { font: var(--t-headline); }
.f-text { font: var(--t-subhead); color: var(--label-secondary); }
.how { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s5); padding: 0 var(--s2); }
.how h3 { font: var(--t-headline); margin: 0 0 6px; }
.how p { font: var(--t-body-loose); color: var(--label-secondary); margin: 0; }
.how a { color: var(--blue); text-decoration: none; }
.home-foot .credit { border-top: 0.5px solid var(--separator); max-width: 420px; }
@media (max-width: 1180px) { .home-grid { grid-template-columns: 1fr 1fr; } .home-grid .features { grid-column: 1 / -1; order: -1; } }
@media (max-width: 760px) {
  .home-col { padding: var(--s5) var(--inset) var(--s10); gap: var(--s6); }
  .hero-title { font: 700 30px/1.12 var(--font); }
  .home-grid { grid-template-columns: 1fr; } .features { grid-template-columns: 1fr; } .how { grid-template-columns: 1fr; }
  .rail { border-radius: var(--r-large); }
}

/* Links styled as buttons must not underline; meta lines stay to one line. */
.btn, .btn:hover { text-decoration: none; }
.sp-meta, .sp-msg { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.home-grid { grid-template-columns: 320px minmax(0, 1fr) 320px; }
@media (max-width: 1180px) { .home-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 760px) { .home-grid { grid-template-columns: 1fr; } }

/* ---------- Document pages scroll as a page, not inside the shell ----------
   The fixed-height grid and hidden body overflow suit the board pages, where
   panes scroll independently. A document wants one scrollbar: the window's. */
body[data-page="home"], body[data-page="doc"] { overflow: auto; }
.app.doc { height: auto; min-height: 100dvh; grid-template-rows: auto 1fr; }
.app.doc .board-col { overflow: visible; }
@media (min-width: 761px) {
  .app.doc { padding-top: var(--s2); }
  .app.doc .toolbar {
    position: sticky; top: var(--s2); z-index: 30;
    min-height: 48px; padding: 0 var(--s2) 0 var(--s3);
    background: var(--material-thick);
    -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur);
    border: 0.5px solid var(--glass-edge-soft);
    border-radius: var(--r-large);
    box-shadow: 0 6px 24px var(--glass-ring), inset 0 1px 0 var(--glass-edge);
  }
}

/* ---------- No double-tap zoom ----------
   Stepping through moves or puzzles means tapping the same button again and
   again; a browser reads that as a double tap and zooms. `manipulation`
   removes that gesture but keeps pinch zoom, so nobody loses the ability to
   enlarge the page. (The board already opts out of all touch gestures.) */
html, body { touch-action: manipulation; }
button, a, input, select, label,
.btn, .chip, .segmented, .tabbar a, .game-row, .level-row, .move, .transport, .swatch-board, .swatch-piece {
  touch-action: manipulation;
}
/* Safari also zooms into a focused control whose text is under 16px, and it
   does not care which way the phone is being held. Keying this to the width
   alone left every field at 11px in landscape — wide enough to miss the
   phone breakpoint, still a touch screen — so tapping one yanked the whole
   page in. A coarse pointer is the condition that actually matters. */
@media (max-width: 760px), (pointer: coarse) {
  input, select, textarea, .field { font-size: max(16px, 1em); }
  .field { min-height: var(--tap); }
}

/* ---------- Site footer (homepage) ---------- */
.site-foot { display: grid; gap: var(--s5); padding-top: var(--s6); border-top: 0.5px solid var(--separator); }
.foot-grid { display: grid; grid-template-columns: 1.5fr 1fr 1fr; gap: var(--s6); align-items: start; }
.foot-brand { display: grid; gap: var(--s3); justify-items: start; }
.foot-brand .brand { gap: var(--s2); }
.foot-name { font: var(--t-headline); }
.foot-brand p { font: var(--t-subhead); color: var(--label-secondary); margin: 0; max-width: 40ch; }
.foot-col { display: grid; gap: 8px; align-content: start; }
.foot-col h4 { font: var(--t-footnote); font-weight: 590; color: var(--label-secondary); margin: 0 0 2px; }
.foot-col a { font: var(--t-subhead); color: var(--label); text-decoration: none; }
.foot-col a:hover { color: var(--blue); }
.foot-bottom { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5); padding-top: var(--s4); border-top: 0.5px solid var(--separator); font: var(--t-caption); color: var(--label-tertiary); }
.foot-bottom a { color: var(--label-secondary); text-decoration: none; font-weight: 590; }
.foot-bottom a:hover { color: var(--label); }
.home-foot .credit { display: none; }
@media (max-width: 760px) { .foot-grid { grid-template-columns: 1fr; gap: var(--s5); } .foot-bottom { flex-direction: column; gap: 6px; } }

/* ---------- What-if variations (Review) ----------
   A branch off the game: the bar names the line, the moves after the branch
   point are drawn in blue so it is never unclear which board you are on. */
.varbar {
  display: grid; gap: var(--s2);
  padding: var(--s3);
  margin-bottom: var(--s4);
  border-radius: var(--r-card);
  border: 0.5px solid color-mix(in srgb, var(--blue) 40%, transparent);
  background: color-mix(in srgb, var(--blue) 10%, transparent);
}
.varbar-head { display: flex; align-items: center; gap: var(--s2); }
.varbar-head .spacer { flex: 1; }
.var-tag {
  font: var(--t-footnote); font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--blue);
}
.var-line {
  font-family: var(--font-mono); font-size: 11px; line-height: 1.6;
  color: var(--label); word-break: break-word;
}
.varbar .hint:empty { display: none; }
.btn-small { min-height: 22px; padding: 0 var(--s3); font: var(--t-caption); }
.move.var .san { color: var(--blue); }
.move.var[aria-current="true"] .san { color: #fff; }
.move.branch { box-shadow: inset 2px 0 0 var(--blue); }
.try-hint { text-align: center; margin-top: var(--s2); }

/* ---------- Review: side searches, phases, retro ---------- */
/* Threat / Deeper / PGN sit after the stepping controls; on a phone they
   wrap onto their own line so the arrows keep their full width. */
.transport { flex-wrap: wrap; }
.transport-tools { display: flex; align-items: center; gap: var(--s2); margin-left: var(--s2); }
.transport .tool { min-height: 28px; padding: 0 var(--s3); font: var(--t-caption2); background: var(--bg-tertiary); box-shadow: var(--shadow-1); }
.transport .tool[aria-pressed="true"] { background: var(--blue); color: #fff; }
.keys-hint { text-align: center; margin-top: var(--s2); color: var(--label-tertiary); }
.live-line { text-align: center; margin-top: var(--s1); font-family: var(--font-mono); font-variant-numeric: tabular-nums; min-height: 15px; }
.live-line:empty { display: none; }
.try-hint.retro { color: var(--blue); font-weight: 600; }

/* Accuracy by phase */
.phases { display: grid; gap: 2px; margin-top: var(--s3); padding-top: var(--s3); border-top: 0.5px solid var(--separator); }
.phase-row {
  display: grid; grid-template-columns: 1fr auto auto; gap: var(--s3); align-items: center;
  font: var(--t-subhead); padding: 1px 0;
}
.phase-row .n { font-variant-numeric: tabular-nums; font-weight: 600; min-width: 36px; text-align: right; }
.phase-row .n.b { color: var(--label-secondary); }
.phase-head { font: var(--t-caption); color: var(--label-secondary); }
.phase-head .n { font-weight: 400; }

/* This-move card extras */
.wdl {
  font: var(--t-caption); font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  color: var(--label-secondary); padding: 2px 8px; border-radius: 999px; background: var(--fill-tertiary);
}
.detail-mate { font: var(--t-subhead); font-weight: 600; color: var(--orange); margin: var(--s2) 0 0; }
.detail-clock { margin-top: var(--s2); font-variant-numeric: tabular-nums; }
.detail-actions { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: var(--s3); }

/* Time per move, under the eval graph */
.times-graph { width: 100%; height: 44px; display: block; margin-top: var(--s2); border-radius: var(--r-control); background: var(--fill-tertiary); cursor: crosshair; }
.times-graph[hidden] { display: none; }

/* Key moments: the decisive moves as a short clickable list */
.moments { display: flex; flex-direction: column; gap: 2px; }
.moment {
  display: grid; grid-template-columns: auto minmax(64px, auto) auto 1fr; gap: var(--s2); align-items: center;
  width: 100%; min-height: 32px; padding: 4px var(--s2); text-align: left;
  border: 0; border-radius: var(--r-control); background: transparent; color: inherit; font: var(--t-subhead); cursor: pointer;
}
.moment:hover { background: var(--fill-tertiary); }
.moment[aria-current="true"] { background: var(--fill-secondary); }
.moment-move { font-weight: 600; font-variant-numeric: tabular-nums; }
.moment .glyph { font-weight: 700; }
.moment-note { color: var(--label-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Where the games come from */
.source-choice { margin-bottom: var(--s1); }

/* A plain checkbox row in the settings sheet, matching the board options */
.popover label.check { display: flex; align-items: center; gap: 8px; font: var(--t-subhead); font-weight: 400; cursor: pointer; }

@media (max-width: 760px) {
  .moment { min-height: var(--tap); }
  .moment-note { white-space: normal; }
  .transport { justify-content: center; row-gap: var(--s2); }
  .transport-tools { flex-basis: 100%; justify-content: center; margin-left: 0; }
  .transport .tool { min-height: var(--tap); padding: 0 var(--s4); font: var(--t-subhead); }
  .keys-hint { display: none; }
  .detail-actions .btn { flex: 1; justify-content: center; }
}

/* ---------- Small controls on a touch screen ----------
   Chips, the leaderboard categories, the footer links and the plain checkbox
   kept their mouse-sized 14–26px boxes on a phone, well short of a fingertip.
   Each grows on a coarse pointer only, so desktop density is unchanged; the
   inline links take negative margins so the bigger hit area doesn't move the
   text around it. */
@media (pointer: coarse) {
  button.chip { min-height: 36px; padding: 0 var(--s3); font: var(--t-footnote); }
  .chip-row, .tc-row { gap: var(--s2); }
  .cat-choice button { min-height: 36px; padding: 0 14px; }
  input[type="checkbox"] { width: 20px; height: 20px; flex: none; }
  label:has(> input[type="checkbox"]) { min-height: var(--tap); }
  .credit-by a, .credit-legal a, .doc-foot a, .foot-bottom a, p.hint > a {
    display: inline-block; padding: 12px 4px; margin: -12px -4px;
  }
  .foot-col { gap: 0; }
  .foot-col a { padding: 8px 0; }
  a.hint { padding-block: 10px; }
}
