/* ===========================================================================
   The opponent picker: faces, and the Bots tab's own shape.
   ===========================================================================

   Companion to js/bot-picker.js (the marks) and js/bots-page.js (the page).

   It lives in its own file rather than in styles.css for the same reason
   home-app.css does: the app's chrome is under active work in more than one
   place at once, and a separate sheet cannot collide with an edit to that one.

   Loaded by BOTH bots.html and index.html, and it has to stay that way. The
   avatar is rendered unconditionally by bot-picker.js, and the row's grid has
   to widen to hold it - a page that drew .picker-bot without this file would
   squeeze a 30px mark into the 8px column the old dot used.

   Two parts:
     1. the faces themselves, which apply everywhere a picker is drawn
     2. the Bots TAB layout, gated on body.has-tabbar so the website keeps the
        plain scrolling page it already had
   ======================================================================== */


/* =======================================================================
   1. The face on every row
   ======================================================================= */

/* The row was `8px 1fr auto` - a dot, the text, the meter. The dot column
   grows into a real avatar; the other two are unchanged, so the strength
   meters stay on the shared right-hand axis that makes nine opponents
   comparable at a glance. */
.picker-bot {
  grid-template-columns: var(--bot-avatar, 30px) 1fr auto;
  gap: 0 12px;
}

/* .picker-dot is no longer rendered (bot-picker.js draws the mark instead).
   The rule in styles.css is harmless and left alone rather than reaching into
   a file someone else may be editing; this is belt and braces in case a cached
   older bot-picker.js is still being served alongside a fresh stylesheet. */
.picker-dot { display: none; }

.picker-avatar {
  position: relative;
  display: block;
  width: var(--bot-avatar, 30px);
  height: var(--bot-avatar, 30px);
  border-radius: 8px;
  /* The one place the bot's colour is set. Everything inside the mark is
     stroked in currentColor, so the rank palette reaches the artwork without
     any per-bot CSS. */
  color: var(--bot-accent, #8b8b84);
  transition: transform .12s ease;
}

/* The plate behind the mark, tinted with the mark's own colour. A pseudo
   element painting currentColor at low opacity rather than color-mix(), which
   Safari only learned in 16.2 - this app still ships to iOS 15. */
.picker-avatar::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: currentColor;
  opacity: .13;
}

.picker-avatar svg {
  position: relative;   /* above the plate */
  display: block;
  width: 100%;
  height: 100%;
  /* The marks already carry about two grid units of their own margin (the
     widest, Net-AB's leaf row, runs 1.95..30.05 of 32). That alone would let a
     square mark graze the plate's 8px corners, so the box gives back a little
     more. Padding on an <svg> sets its viewport to the content box, so the
     viewBox simply scales into what is left. */
  padding: 1.5px;
  box-sizing: border-box;
  overflow: visible;
}

/* A face lights up under the finger, which is the only affordance a row has
   left now that it is not a card. */
.picker-bot:hover:not(:disabled) .picker-avatar::before { opacity: .2; }
.picker-bot:active:not(:disabled) .picker-avatar { transform: scale(.94); }

/* Unavailable means unavailable: the mark goes grey with the name and the
   blurb rather than staying the only bright thing in a dimmed row. */
.picker-bot:disabled .picker-avatar { color: #55554f; }
.picker-bot:disabled .picker-avatar::before { opacity: .1; }

/* Silver and gold at 13% on a near-black plate are nearly white; the ladder's
   own colours are chosen against the rank cards, not against this. Dropping
   the plate a little keeps the four server bots reading as four DIFFERENT
   colours instead of three bright ones and a blue. */
.picker-bot[data-bot="hard"] .picker-avatar::before,
.picker-bot[data-bot="medium"] .picker-avatar::before { opacity: .1; }


/* =======================================================================
   2. The Bots tab
   =======================================================================
   Web keeps the ordinary scrolling page: a topbar, a title, and as much room
   below it as the roster needs. Everything from here down is native only.

   The problem this solves: the page scrolled as one piece, so "Choose your
   opponent" scrolled with it and ended up jammed against the status bar -
   under the notch on a tall phone. A title that slides under the clock reads
   as a layout bug even when everything else is fine.

   So the page becomes two parts: a header that does not move, and a list that
   does. On a 390x844 phone the nine rows fit without scrolling at all; on a
   shorter one (SE, 375x667) the list scrolls and the header stays put, which
   is the behaviour the header was missing. */
body.has-tabbar .bots-page {
  display: flex;
  flex-direction: column;
  /* Pinned to the viewport rather than to the parent: `height: 100%` against
     body would collapse to content height, and the header only stays put if
     the page has a height for the list to be the remainder OF.

     body.has-tabbar already reserves the bar with padding-bottom
     (--tabbar-core-h + the bottom inset, republished by tabbar.js whenever it
     measures), so subtracting the same two here lands the page exactly on the
     top of the bar with nothing left over to scroll. */
  height: calc(100vh - var(--tabbar-core-h, 52px) - env(safe-area-inset-bottom));
  min-height: 0;
  max-width: 640px;
  /* The header supplies the top inset itself; .profile-page's own padding
     would put it above a header that is meant to reach the screen's edge. */
  padding: 0 max(14px, env(safe-area-inset-right)) 0 max(14px, env(safe-area-inset-left));
  overflow: hidden;
}

/* 100vh on iOS is the tallest the viewport ever gets - it ignores the browser
   chrome, so the foot of the page hides behind it. dvh is the fix and is what
   the rest of the app already uses; it needs Safari 15.4 and this app ships to
   15.0, hence the vh above as the floor rather than the target. */
@supports (height: 100dvh) {
  body.has-tabbar .bots-page {
    height: calc(100dvh - var(--tabbar-core-h, 52px) - env(safe-area-inset-bottom));
  }
}

/* ---- the header that stays put ---- */
body.has-tabbar .bots-head {
  flex: 0 0 auto;
  padding-top: calc(10px + env(safe-area-inset-top));
  padding-bottom: 10px;
  /* The list scrolls underneath, so the band needs a floor of its own or the
     rows would show through behind the title. */
  background: var(--color-bg);
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

/* ---- the part that scrolls ---- */
body.has-tabbar .bots-grid {
  flex: 1 1 auto;
  min-height: 0;             /* or the grid refuses to shrink and the page scrolls */
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  /* Rubber-banding the whole page behind a fixed header is the other half of
     "the title ended up at the top of my phone". */
  overscroll-behavior: contain;
  gap: 4px;
  padding-bottom: 10px;
  /* A grid taller than its rows stretches them, and `normal` is stretch. The
     scroll area is `flex: 1 1 auto`, so on any phone where the roster is
     shorter than the space it has - which is every phone, since the two series
     are four bots and six - the leftover height was being divided BETWEEN the
     two rows instead of falling below them. That put ~200px of nothing between
     "Strategist" and "ACE SERIES", which reads as the second list failing to
     load rather than as spare room. */
  align-content: start;
}

/* Nine rows, two series headers and a note have to fit a phone. These are the
   savings, in order of how little they cost:
   the series header loses its generous lead, and the rows tighten by 2px. */
body.has-tabbar .bots-grid .picker-series { padding: 10px 0 2px; }
body.has-tabbar .bots-grid .picker-head { padding: 0 4px 8px; }
body.has-tabbar .bots-grid .picker-bot { padding: 9px 4px; }
body.has-tabbar .bots-grid .picker-note { margin: 6px 4px 0; padding: 8px 0 0; }

/* When the series stack, the hairline belongs BETWEEN them rather than beside
   them. styles.css already handles that under 700px. The gap is 700-759px:
   .bots-grid is still one column there (it only splits at 760) but the 700px
   media query has stopped applying, so .picker-grid's side-by-side border-left
   comes back and draws a rule down the left of the second series. An iPad mini
   in portrait is 744, so this band is a real device, not a hypothetical. */
@media (min-width: 701px) and (max-width: 759px) {
  body.has-tabbar .bots-grid .picker-series + .picker-series {
    border-left: 0;
    border-top: 1px solid rgba(255, 255, 255, 0.07);
  }
}


/* =======================================================================
   3. The title
   =======================================================================
   Centred on both web and app. It is the page's only heading and it sits over
   two equal columns; left-aligning it made it look like the first column's
   label rather than the page's name. */
.bots-title,
.bots-sub {
  text-align: center;
}

body.has-tabbar .bots-title {
  margin: 0;
  font-size: 19px;
  letter-spacing: -.01em;
}
body.has-tabbar .bots-sub {
  margin: 2px 0 0;
  font-size: 12px;
}


/* =======================================================================
   4. "Which side?" — the seat dialog
   =======================================================================
   Built by js/seat-choice.js and shown between picking an opponent and the
   first move. It lives here rather than in styles.css because it is part of
   the picker's flow, and this is the one sheet BOTH pages that draw a picker
   already load (see the note at the top of this file).

   The card reuses .overlay-screen / .win-card / .lobby-close from styles.css,
   so only the two choices below are new. */

.seat-choice-card { min-width: 300px; max-width: 420px; padding: 32px 26px 26px; }
.seat-choice-card .win-title { margin: 4px 0 6px; font-size: 1.35rem; }
.seat-choice-sub { margin: 0 0 20px; }
.seat-choice-sub:empty { display: none; }

/* Two equal columns, because the choice is symmetrical and a stacked list
   would imply one of them is the default. They stack only when the phone is
   too narrow to hold both at a comfortable tap size. */
.seat-choice-options { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media (max-width: 380px) {
  .seat-choice-options { grid-template-columns: 1fr; }
}

.seat-choice-opt {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 18px 12px 14px;
  background: var(--color-surface-raised, rgba(255,255,255,0.045));
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md, 8px);
  color: var(--color-text-primary);
  cursor: pointer;
  transition: background .12s ease, border-color .12s ease, transform .12s ease;
}
.seat-choice-opt:hover { background: rgba(255,255,255,0.075); }
.seat-choice-opt:active { transform: scale(.97); }
.seat-choice-opt:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}
/* The side played last, marked rather than pre-selected: it is where focus
   lands, so Enter repeats the last game, but nothing is chosen until a press.
   A filled-in "active" state would read as an answer already given. */
.seat-choice-opt.is-last { border-color: var(--color-accent); }

.seat-choice-name { font-size: 15px; font-weight: 700; letter-spacing: -.005em; }
.seat-choice-note { font-size: 11.5px; color: var(--text-dim); line-height: 1.3; }

/* The pieces themselves, borrowed from the active board theme so a player who
   changed their pieces is choosing between the ones they will actually see. */
.seat-choice-pawn {
  width: 34px; height: 34px; border-radius: 50%; margin-bottom: 6px;
  box-shadow: inset 0 2px 3px rgba(255,255,255,.35), 0 2px 5px rgba(0,0,0,.45);
}
.seat-choice-pawn-1 {
  background: radial-gradient(circle at 35% 30%, var(--pt1-pawn-hi), var(--pt1-pawn-base));
  border: 3px solid var(--pt1-pawn-rim);
}
.seat-choice-pawn-2 {
  background: radial-gradient(circle at 35% 30%, var(--pt2-pawn-hi), var(--pt2-pawn-base));
  border: 3px solid var(--pt2-pawn-rim);
}
