/*
 * The deck: the phone layout of the board's figure (js/deck.js builds what
 * this sheet styles). Linked from index.html under the same media query as
 * css/mobile.css and after the other three phone sheets, because the status
 * strip overrides mobile-modes.css's .turn-status and .info sizes; a desktop
 * never loads it, and every rule in here is under body.phone or names an
 * element only the deck builds.
 *
 * The big board's figure is one grid for everything around the board: the
 * status strip above it (row 1), the two name plates (rows 2 and 4), the
 * board (row 3), the ticker with the move buttons (row 5), the analysis
 * graph (row 6) and the deck (row 7, the rest of the room): live, actions,
 * chips and readouts, the readouts the one row that scrolls. Rows a mode
 * lacks are empty tracks that cost nothing; the 4px between rows comes from
 * margins, so a hidden row costs nothing either. style.css's `order` numbers
 * are untouched: explicit grid-row placement simply does not consult them.
 * On a phone turned on its side the same grid turns (the last section): the
 * board takes the left column at its room's height, the rows stack beside
 * it, and the bar is a rail at the right edge.
 */

:root {
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
}

/* ---------- The figure's grid ---------- */

/*
 * style.css starts the boards row at flex-start and centres the figure's
 * items; both would leave the deck without height (a content-sized figure
 * clipped by #board-wrap, a centred #deck with no stretch), so the three
 * are overridden here, under body.phone only.
 */
body.phone main > #board-wrap {
  margin-top: 0;
}

body.phone .boards {
  flex: 1 1 auto;
  min-height: 0;
  align-items: stretch;
}

body.phone .board-figure {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-rows: auto auto auto auto auto auto minmax(0, 1fr);
  gap: 0;
  width: 100%;
  max-width: none;
  min-height: 0;
  align-items: stretch;
}

/* The second figure never shows on a phone: Play as turns the board instead (section 11 of the spec). */
body.phone #board2-figure {
  display: none;
}

/*
 * The stored Both sides flag may still add .dual and unhide the caption
 * (a desktop preference in the same browser profile); neither reaches the
 * phone figure.
 */
body.phone .boards.dual .board-figure {
  width: 100%;
  flex: none;
  max-width: none;
}

body.phone #board-caption {
  display: none;
}

body.phone .board-figure > #deck-status {
  grid-row: 1;
  grid-column: 1 / -1;
}

body.phone .board-figure[data-bottom="white"] > .plates .plate[data-side="black"],
body.phone .board-figure[data-bottom="black"] > .plates .plate[data-side="white"] {
  grid-row: 2;
  grid-column: 1 / -1;
  margin-top: 4px;
}

/*
 * The board is capped by its measured room (--board-max, js/mobile.js
 * fitBoard, written on body and #board-wrap). The fallback keeps the rule
 * valid before the first fit and after a stage mode removes the property.
 */
body.phone .board-figure > #board {
  grid-row: 3;
  grid-column: 1 / -1;
  justify-self: center;
  width: min(100%, var(--board-max, 100%));
  margin-top: 4px;
}

body.phone .board-figure[data-bottom="white"] > .plates .plate[data-side="white"],
body.phone .board-figure[data-bottom="black"] > .plates .plate[data-side="black"] {
  grid-row: 4;
  grid-column: 1 / -1;
  margin-top: 4px;
}

body.phone .board-figure > .ticker {
  grid-row: 5;
  grid-column: 1;
  margin-top: 4px;
}

body.phone .board-figure > .move-nav {
  grid-row: 5;
  grid-column: 2;
  margin-top: 4px;
}

body.phone .board-figure > #analysis-graph {
  grid-row: 6;
  grid-column: 1 / -1;
  margin-top: 4px;
  max-width: none;
}

body.phone .board-figure > #deck {
  grid-row: 7;
  grid-column: 1 / -1;
  align-self: stretch;
  min-height: 0;
  margin-top: 4px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* Absolute children are placed from --board-top as before and take no track. */
body.phone .board-figure > #move-ghost,
body.phone .board-figure > .moves-sheet {
  margin: 0;
}

/* The moves overlay is sized to the board, not the figure (js/scoreboard.js writes --board-h). */
body.phone .board-figure > .moves-sheet {
  max-height: var(--board-h, 100%);
}

/* The plates are a scoreboard line each; the ticker row holds the two move buttons at its right. */
body.phone .board-figure > .plates .plate {
  min-height: 28px;
  padding: 2px 8px;
}

/* The ticker is a button (a tap opens the moves): 44px on its own, as beside the move buttons. */
body.phone .board-figure > .ticker {
  min-height: 44px;
  padding: 2px 10px;
}

body.phone .board-figure > .move-nav {
  gap: 4px;
  margin-left: 8px;
}

body.phone .board-figure > .move-nav .move-nav-btn {
  min-width: 44px;
  height: 36px;
  padding: 0 8px;
}

/* "3 / 9" and "No moves yet" are the ticker's to say. */
body.phone .board-figure > .move-nav .move-nav-at {
  display: none;
}

/* ---------- Below the floor ---------- */

/*
 * fitBoard sets body.deck-tight when the board would fall under 280px: the
 * graph hides first (its toggle stays on, the readouts say so), and should
 * the fixed rows plus a 280px board still exceed the room, the board area
 * scrolls the whole figure, so no row collapses and nothing is cut.
 */
body.phone.deck-tight #analysis-graph {
  display: none;
}

body.phone.deck-tight #board-wrap {
  overflow-y: auto;
  overscroll-behavior: contain;
}

body.phone.deck-tight .boards {
  align-items: flex-start;
}

body.phone.deck-tight .board-figure {
  height: auto;
  min-height: 100%;
}

/* ---------- The status strip ---------- */

/*
 * One sentence above the board. Content-sized, never clamped: the kid face
 * reserves two lines so a one-to-two-line change never moves the board; the
 * ratchet (--status-min, js/deck.js measure) keeps the tallest height seen
 * in the mode; past six lines the strip scrolls inside itself. These sizes
 * override mobile-modes.css's .turn-status and .info, which is why this
 * sheet is linked last.
 */
body.phone #deck-status {
  font-size: 18px;
  line-height: 1.3;
  min-height: max(63px, var(--status-min, 0px));
  max-height: calc(7.8em + 16px);
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
}

body.phone #deck-status[data-face="workbench"] {
  font-size: 16px;
  min-height: max(36px, var(--status-min, 0px));
  max-height: calc(7.8em + 12px);
}

body.phone #deck-status.dense {
  font-size: 16px;
}

body.phone #deck-status > .turn-status,
body.phone #deck-status > .info,
body.phone #deck-status > .deck-hint {
  font-size: inherit;
  line-height: inherit;
  padding: 8px 12px;
  margin: 0;
  flex: none;
}

body.phone #deck-status[data-face="workbench"] > .turn-status,
body.phone #deck-status[data-face="workbench"] > .info,
body.phone #deck-status[data-face="workbench"] > .deck-hint {
  padding: 6px 10px;
}

/* The mode's hint standing in for a status, and a plain .info: the same box as a status. */
body.phone #deck-status > .deck-hint,
body.phone #deck-status > .info {
  display: block;
  font-weight: 600;
  border-radius: 10px;
  background: var(--panel-2);
}

body.phone #deck-status > .info:empty {
  display: block;
  min-height: 1.3em;
}

/* Position lab's message rides under its status in the same strip. */
body.phone #deck-status > .lab-message {
  margin: 4px 0 0;
  font-size: 0.9em;
}

/*
 * The contents sit in the middle of the reserved height by auto margins,
 * not justify-content: center, because auto margins resolve to nothing
 * once the contents are taller than the strip, so the first line stays at
 * the top where the scroll can start; centring would push it out of reach
 * above the box.
 */
body.phone #deck-status > :first-child {
  margin-top: auto;
}

body.phone #deck-status > :last-child {
  margin-bottom: auto;
}

/* ---------- The deck's rows ---------- */

/* Live: a clock row or a prompt; the mode's own look at its own size. */
body.phone .deck-live {
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

body.phone .deck-live .coords-prompt {
  padding: 6px 12px;
  font-size: 1.9rem;
}

/* Coordinates' clock sits at the prompt's right, not on a line of its own, so the live row is the same height in practice and in a sprint and the board never moves at Start. */
body.phone .deck-live:has(> .coords-prompt) {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  column-gap: 8px;
}

body.phone .deck-live:has(> .coords-prompt) > .sprint-clock {
  margin: 0;
  padding: 0 8px;
}

body.phone .deck-live .sprint-status {
  padding: 6px 12px;
}

body.phone .deck-live .sprint-clock {
  font-size: 2rem;
}

/*
 * Actions: the mode's own rows and buttons, moved whole. Big (52px, bold)
 * in the kid face, 44px in the workbench; a label is never cut: it may
 * wrap inside its button, and a row of three may wrap to two lines.
 */
body.phone .deck-actions {
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

body.phone .deck-actions .button-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

body.phone #deck[data-face="kid"] .deck-actions .button-row {
  gap: 8px 12px;
}

body.phone .deck-actions .button-row button,
body.phone .deck-actions > button {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 44px;
  padding: 6px 8px;
  font-size: clamp(14px, 4.4vw, 17px);
  line-height: 1.15;
  white-space: normal;
}

body.phone #deck[data-face="kid"] .deck-actions .button-row button,
body.phone #deck[data-face="kid"] .deck-actions > button {
  min-height: 52px;
  font-weight: 700;
}

/* A bare button seated alone is a row of one. */
body.phone .deck-actions > button {
  width: 100%;
}

/* The tactics drills' counter sits between Previous and Next. */
body.phone .deck-actions .tactics-counter {
  align-self: center;
  padding: 0 4px;
  font-size: 15px;
  white-space: nowrap;
}

/* A checkbox in an action row (Position lab's Think row) keeps its native look beside the button. */
body.phone .deck-actions .button-row .field.inline {
  flex: 1 1 auto;
  min-height: 44px;
  font-size: 15px;
}

/*
 * Chips: 36px pills in a 44px strip that scrolls sideways and never wraps.
 * A swipe past the end must not become the browser's back gesture; the
 * last chip is cut at the edge rather than aligned to it, and a fade says
 * there is more.
 */
body.phone .deck-chips {
  flex: none;
  display: flex;
  align-items: stretch;
  gap: 8px;
  height: 44px;
  padding: 0 8px;
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

body.phone .deck-chips::-webkit-scrollbar {
  display: none;
}

body.phone .deck-chips.can-scroll-right {
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent);
  mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent);
}

/*
 * Every pill and segment rule is a descendant selector, never a child one:
 * a declared container (Fork's layer box) is moved whole and dissolves
 * into the row, so its labels are grandchildren.
 */
body.phone .deck-chips [data-deck-group] {
  display: contents;
}

body.phone .deck-chips [data-deck-group] > .legend-title {
  display: none;
}

/* A hidden chip stays hidden at any depth (Coordinates' strikes rule until Sprint is picked). */
body.phone .deck-chips [hidden] {
  display: none;
}

/*
 * The pill: the element itself is the 44px hit area (4px of transparent
 * padding top and bottom) and ::before draws the 36px pill behind its text.
 */
body.phone .deck-chips .field.inline,
body.phone .deck-chips .deck-chip,
body.phone .deck-chips button:not(.deck-chip) {
  position: relative;
  isolation: isolate;
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 44px;
  min-height: 0;
  margin: 0;
  padding: 4px 14px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  box-shadow: none;
  color: var(--text);
  font-size: 16px;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
}

body.phone .deck-chips .field.inline::before,
body.phone .deck-chips .deck-chip::before,
body.phone .deck-chips button:not(.deck-chip)::before {
  content: "";
  position: absolute;
  inset: 4px 0;
  z-index: -1;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--panel-2);
}

body.phone .deck-chips .field.inline span {
  font-size: 16px;
  color: var(--text);
}

body.phone .deck-chips .deck-chip[aria-pressed="true"]::before,
body.phone .deck-chips .deck-chip[data-armed]::before {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
  background: var(--accent-soft);
}

/* A chip that switches something on (aria-pressed) wears a ring before its words that fills when it is on; a verb chip (Flip, Play as) has none, so the two kinds read apart. */
body.phone .deck-chips .deck-chip[aria-pressed]::after {
  content: "";
  order: -1;
  flex: none;
  width: 12px;
  height: 12px;
  border: 2px solid var(--muted);
  border-radius: 50%;
  box-sizing: border-box;
}

body.phone .deck-chips .deck-chip[aria-pressed="true"]::after {
  border-color: var(--accent);
  background: var(--accent);
}


body.phone .deck-chips .deck-chip-glyph {
  width: 24px;
  height: 24px;
  flex: none;
}

body.phone .deck-chips .deck-chip-glyph svg {
  width: 100%;
  height: 100%;
}

/* The king on a disc of the other colour, so both sides read on the dark pill. */
body.phone .deck-chips .deck-chip-play-as .deck-chip-glyph,
body.phone .deck-chips .deck-chip-summary .deck-chip-glyph {
  border-radius: 50%;
  padding: 2px;
  box-sizing: border-box;
  background: var(--panel);
}

body.phone .deck-chips .deck-chip-glyph[data-side="black"] {
  background: var(--piece-white-color, #f5f5f5);
}

body.phone .deck-chips .deck-chip-turn {
  font-size: 18px;
  line-height: 24px;
  text-align: center;
}

/* Fork's streak beside Find it yourself: plain text in the row. */
body.phone .deck-chips .tactics-streak {
  align-self: center;
  font-size: 14px;
  color: var(--muted);
  white-space: nowrap;
}

/*
 * The checkbox itself is hidden and the pill fills when it is checked. Both
 * are gated on :has, because an engine without it would show a pill with no
 * state at all: there, the native checkbox stays inside the pill.
 */
@supports selector(:has(*)) {
  body.phone .deck-chips .field.inline input[type="checkbox"] {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: 0;
    opacity: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    pointer-events: none;
  }

  body.phone .deck-chips .field.inline:has(:checked)::before {
    border-color: var(--accent);
    box-shadow: inset 0 0 0 1px var(--accent);
    background: var(--accent-soft);
  }

  body.phone .deck-chips .field.inline:has(:focus-visible)::before {
    outline: 2px solid var(--accent);
    outline-offset: 1px;
  }

  body.phone .deck-chips .radio input[type="radio"] {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: 0;
    opacity: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    pointer-events: none;
  }

  body.phone .deck-chips .radio:has(input:checked) {
    color: var(--text);
    font-weight: 700;
  }

  body.phone .deck-chips .radio:has(input:checked)::before {
    background: var(--accent-soft);
  }

  /* The keyboard's focus lands on the 1px input: the segment shows it instead. */
  body.phone .deck-chips .radio:has(input:focus-visible) {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
  }

  /* A disabled segment (Practice / Sprint while a sprint runs) fades and takes no tap. */
  body.phone .deck-chips .radio:has(input:disabled) {
    opacity: .5;
    pointer-events: none;
  }
}

/*
 * A radio group is a segmented control: its labels are the segments, the
 * checked one filled. A div.field holding one dissolves and its own label
 * (the group's name) is hidden.
 */
body.phone .deck-chips .field:not(.inline) {
  display: contents;
}

body.phone .deck-chips .field:not(.inline) > span {
  display: none;
}

/*
 * The group is the full 44px of the strip (its segments are the hit
 * areas, like the pills); the 36px capsule is drawn by ::before, with the
 * 4px above and below it transparent, as on a pill.
 */
body.phone .deck-chips .radio-group {
  position: relative;
  isolation: isolate;
  flex: none;
  display: inline-flex;
  align-items: stretch;
  gap: 0;
  height: 44px;
  margin: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  overflow: visible;
}

body.phone .deck-chips .radio-group::before {
  content: "";
  position: absolute;
  inset: 4px 0;
  z-index: -1;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--panel-2);
}

body.phone .deck-chips .radio {
  position: relative;
  flex: none;
  display: inline-flex;
  align-items: center;
  min-height: 0;
  margin: 0;
  padding: 0 14px;
  border: 0;
  border-radius: 0;
  background: transparent;
  font-size: 16px;
  font-weight: 600;
  white-space: nowrap;
}

/* The filled segment: the 36px band inside the 44px, clipped to the capsule's ends. */
body.phone .deck-chips .radio::before {
  content: "";
  position: absolute;
  inset: 4px 0;
  z-index: -1;
  background: transparent;
}

body.phone .deck-chips .radio:first-child::before {
  border-radius: 999px 0 0 999px;
}

body.phone .deck-chips .radio:last-child::before {
  border-radius: 0 999px 999px 0;
}

body.phone .deck-chips .radio + .radio::before {
  border-left: 1px solid var(--line);
}

/*
 * Readouts: the one scroller under the board. A seated move list is no
 * longer its own 220px scroller (that would capture every drag).
 */
body.phone .deck-readouts {
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

body.phone .deck-readouts > * {
  flex: none;
}

/* While there is more below, the last line fades rather than ending in a cut: the fade is the scroll cue, as at the chip row's right edge. */
body.phone .deck-readouts.can-scroll-down {
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 16px), transparent);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 16px), transparent);
}

body.phone .deck-readouts .move-list {
  max-height: none;
  overflow: visible;
}

/* The ticker already says "No moves yet": the move list's empty line would say it twice, 100px apart. */
body.phone .deck-readouts .move-list > .hint:only-child {
  display: none;
}

body.phone .deck-readouts > #hint {
  font-size: 15px;
  line-height: 1.35;
  color: var(--muted);
}

body.phone .deck-readouts > .hint {
  font-size: 15px;
  line-height: 1.35;
}

body.phone .deck-readouts > .lesson {
  padding: 8px 12px;
  font-size: 15px;
  line-height: 1.4;
}

/* Sticky, so the one line fitBoard gave up the board for is the line on screen while the moves scroll under it. */
body.phone .deck-readouts > .deck-note {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--bg);
  font-size: 14px;
  color: var(--muted);
}

/* The legend is one wrapping row of swatches; its title says nothing a child needs. */
body.phone .deck-readouts > #legend {
  flex-direction: row;
  flex-wrap: wrap;
  gap: 6px 14px;
  padding: 6px 10px;
  font-size: 14px;
}

body.phone .deck-readouts > #legend .legend-title {
  display: none;
}

/* The dial: a mode's one slider under the board, full width, with its readout, dressed like a sheet slider (js/sheet.js decorates it: [-] and [+] after it, the readout tappable). */
body.phone .deck-readouts > label.field {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 2px;
  font-size: 15px;
}

body.phone .deck-readouts > label.field input[type="range"] {
  width: 100%;
  min-height: 44px;
  height: 44px;
  margin: 0;
}

body.phone .deck-readouts > label.field:has(> input[type="range"][data-stepped]) {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr) 44px;
  grid-template-rows: auto 44px;
  column-gap: 6px;
  row-gap: 2px;
  align-items: center;
}

body.phone .deck-readouts > label.field:has(> input[type="range"][data-stepped]) > :not(input[type="range"]):not(.sheet-step) {
  grid-column: 1 / -1;
}

body.phone .deck-readouts > label.field:has(> input[type="range"][data-stepped]) > input[type="range"] {
  grid-column: 2;
  grid-row: 2;
}

body.phone .deck-readouts > label.field > .sheet-step {
  grid-row: 2;
  width: 44px;
  min-height: 44px;
  padding: 0;
  font-size: 24px;
  line-height: 1;
  font-weight: 600;
  border-radius: 10px;
}

body.phone .deck-readouts > label.field > .sheet-step-down {
  grid-column: 1;
}

body.phone .deck-readouts > label.field > .sheet-step-up {
  grid-column: 3;
}

body.phone .deck-readouts > label.field > span > b.value[role="button"] {
  display: inline-block;
  cursor: pointer;
  text-decoration: underline dotted;
  text-underline-offset: 3px;
  padding: 10px 8px;
  margin: -10px -8px;
  line-height: 24px;
  border-radius: 6px;
}

body.phone .deck-readouts > label.field input.sheet-exact {
  width: 6.5em;
  height: 28px;
  min-height: 0;
  margin: -4px 0;
  padding: 0 6px;
  font-size: 16px;
  font-weight: 600;
  color: var(--accent);
}

/* A readout that is a whole block (Position lab's setup or play block) keeps its own layout. */
body.phone .deck-readouts > .lab-setup,
body.phone .deck-readouts > .lab-play {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* A drawer seated as a readout (Bot vs Bot's Session tally) is open; its title reads as a heading. */
body.phone .deck-readouts > .drawer {
  border: 0;
  background: transparent;
}

body.phone .deck-readouts > .drawer > .drawer-title {
  min-height: 0;
  padding: 4px 0;
  pointer-events: none;
}

body.phone .deck-readouts > .drawer > .drawer-title::before {
  display: none;
}

body.phone .deck-readouts > .drawer > .drawer-body {
  padding: 0;
}

/* Knight sprint's ledger, score box and bests, Puzzles' tiles: as the modes draw them, a touch smaller. */
body.phone .deck-readouts > .score-box {
  padding: 10px 12px;
}

body.phone .deck-readouts > .bests {
  font-size: 14px;
}

/* ---------- A stage mode: the strip, the live row and the flow ---------- */

/*
 * The board area is the one scroller (body.staged, css/mobile.css). The strip
 * is one sticky element holding the status, then the actions and chips (the
 * readouts are hidden here); two sticky siblings would slide over each other
 * as the page scrolls. The live row (My games' lookup form) sits under the
 * strip in the flow and scrolls away with the page; what the plan flows
 * after the stage (the Arena's Tally and Standings, the Leaderboard's
 * table, My games' card and list) follows it in #deck-flow. The strip's
 * height is --deck-h on body (js/deck.js measure), 0 when it is hidden, and
 * the Arena's grid reads it (css/mobile-workbench.css).
 */
body.phone #deck-strip {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 4px;
  width: 100%;
  background: var(--bg);
}

body.phone #deck-strip > #deck {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* The board area centres its items; the lifted live row and the flow take the width like the strip. */
body.phone #board-wrap > .deck-live {
  flex: none;
  width: 100%;
}

body.phone #deck-flow {
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
}

/* A flowed drawer is open and its title is a plain heading, not a fold. */
body.phone #deck-flow > .drawer {
  border: 0;
  background: transparent;
}

body.phone #deck-flow > .drawer > .drawer-title {
  min-height: 0;
  padding: 4px 0;
  pointer-events: none;
}

body.phone #deck-flow > .drawer > .drawer-title::before {
  display: none;
}

body.phone #deck-flow > .drawer > .drawer-body {
  padding: 0;
}

/* A lookup form rebuilt inside its flowed block (profile.js, left-book.js)
   is lifted to the live row on the next frame; for that one frame it is not
   a second form under the stage. */
body.phone #deck-flow form.pf-lookup {
  display: none;
}

/* The Leaderboard with no server (or no games): the stage's card already
   says what to do, and the panel's one-paragraph copy of it, flowed right
   under the card, would say it twice. */
body.phone #deck-flow > .lb-body > .hint:only-child {
  display: none;
}

/* ---------- The panel while the deck has the rest ---------- */

/* The mode's name is in the bar; the title stays in the panel for the desktop and for refresh(). */
body.phone #mode-title {
  display: none;
}

/* An emptied drawer (nothing left in it but anchors) says where its contents went. */
body.phone #panel .drawer > .drawer-body:not(:has(> :not([hidden])))::after {
  content: "Shown under the board.";
  color: var(--muted);
  font-size: 0.85rem;
}

/* ---------- Short landscape: the board at the left, the column at the right, the bar a rail ---------- */

/*
 * A phone on its side (the sub-query the index.html media attribute already
 * admits). The same figure grid turns: the board takes column 1 and every
 * row, sized by its height (fitBoard in js/mobile.js writes the board area's
 * height as --board-max and the width follows); column 2 is an 8px gutter;
 * the status, the plates with the ticker row between them, the graph and
 * the deck stack in column 3, the move buttons in column 4 beside the
 * ticker. Nothing moves between the figure and anywhere else when the phone
 * turns. The bar becomes a 56px rail at the right edge, Modes at the top and
 * Settings at the bottom, and main keeps a track free under it; the sheet
 * docks beside the board over the column (css/mobile-sheet.css). The
 * header stays hidden (css/mobile.css hides it on every phone).
 */
@media (max-height: 520px) and (orientation: landscape) {
  body.phone main {
    display: grid;
    grid-template-columns: minmax(0, 1fr) calc(56px + var(--safe-r));
    grid-template-rows: minmax(0, 1fr);
    gap: 0;
    /* The left inset is a notch's, the bottom one the home indicator's: the board never sits under either (the rail pads the same way). */
    padding: 6px 8px max(6px, var(--safe-b)) max(8px, var(--safe-l));
  }

  body.phone main > #board-wrap {
    grid-column: 1;
    grid-row: 1;
  }

  body.phone .board-figure {
    grid-template-columns: var(--board-max, 50%) 8px minmax(0, 1fr) auto;
    grid-template-rows: auto auto auto auto auto auto minmax(0, 1fr);
  }

  body.phone .board-figure > #board {
    grid-row: 1 / -1;
    grid-column: 1;
    align-self: start;
    justify-self: start;
    width: 100%;
    margin-top: 0;
  }

  body.phone .board-figure > #deck-status {
    grid-column: 3 / -1;
  }

  body.phone .board-figure[data-bottom="white"] > .plates .plate[data-side="black"],
  body.phone .board-figure[data-bottom="black"] > .plates .plate[data-side="white"] {
    grid-column: 3 / -1;
  }

  body.phone .board-figure > .ticker {
    grid-row: 3;
    grid-column: 3;
  }

  body.phone .board-figure > .move-nav {
    grid-row: 3;
    grid-column: 4;
  }

  body.phone .board-figure[data-bottom="white"] > .plates .plate[data-side="white"],
  body.phone .board-figure[data-bottom="black"] > .plates .plate[data-side="black"] {
    grid-column: 3 / -1;
  }

  body.phone .board-figure > #analysis-graph {
    grid-row: 5;
    grid-column: 3 / -1;
  }

  body.phone .board-figure > #deck {
    grid-column: 3 / -1;
  }

  /* The absolute children cover the board, not the figure: as wide as the board's column. */
  body.phone .board-figure > #move-ghost,
  body.phone .board-figure > .moves-sheet {
    width: var(--board-max, 50%);
  }

  /*
   * Below the floor on a side-on phone: the column, not the board, is what
   * runs out (fitBoard sets deck-tight when the fixed rows and the graph
   * would leave the readouts under two lines), so the graph hides as in
   * portrait, the board stays its room's height and the figure never
   * scrolls: the readouts give instead.
   */
  body.phone.deck-tight #board-wrap {
    overflow: hidden;
  }

  body.phone.deck-tight .boards {
    align-items: stretch;
  }

  body.phone.deck-tight .board-figure {
    height: auto;
    min-height: 0;
  }

  /* ---- The rail: the same two buttons, stacked at the right edge ---- */

  body.phone .mobile-bar {
    top: 0;
    bottom: 0;
    left: auto;
    right: 0;
    width: calc(56px + var(--safe-r));
    height: auto;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: 8px;
    padding: max(6px, var(--safe-t)) calc(2px + var(--safe-r)) max(6px, var(--safe-b)) 2px;
    border-top: 0;
    border-left: 1px solid var(--line);
    box-shadow: -6px 0 20px rgba(0, 0, 0, 0.3);
  }

  /* The tile above a two-line label (MODES, then the mode's name); the glyph above Settings. */
  body.phone .mbar-btn {
    flex-direction: column;
    justify-content: center;
    gap: 4px;
    width: 100%;
    height: auto;
    min-height: 64px;
    padding: 6px 0;
    font-size: 11px;
    text-align: center;
  }

  body.phone .mbar-modes {
    justify-content: center;
    gap: 4px;
  }

  body.phone .mbar-modes-text {
    align-items: center;
    max-width: 100%;
  }

  /* MODES and its chevron on one line of the 56px, tighter than the bar's. */
  body.phone .mbar-modes-caption {
    font-size: 11px;
    letter-spacing: 0.04em;
    white-space: nowrap;
  }

  /* A long name wraps at its words and never inside one ("Coordinates" overhangs the 56px by a few px rather than ending in "Coordinate / s"); up to three lines, the rail has the height. */
  body.phone .mbar-modes-name {
    font-size: 10px;
    letter-spacing: -0.02em;
    line-height: 1.15;
    max-width: none;
    white-space: normal;
    overflow-wrap: normal;
    hyphens: manual;
    overflow: visible;
    text-overflow: clip;
  }

  body.phone .mbar-label {
    white-space: normal;
  }

  /* ---- A stage mode: the strip is one wrapping row across the top ---- */

  /*
   * The status takes the room (flex: 1) with the actions and chips inline
   * after it; the row is content-sized and measured into --deck-h like any
   * strip (js/deck.js), never assumed, at least 44px when it holds anything
   * and hidden when it does not. The live block (My games' lookup form)
   * sits under it in the flow; the stage takes what remains and scrolls
   * with the page. The Arena reads --deck-h for its ladder
   * (css/mobile-workbench.css).
   */
  body.phone #deck-strip {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 8px;
    min-height: 44px;
  }

  body.phone #deck-strip > #deck-status {
    flex: 1 1 200px;
    min-width: 0;
  }

  body.phone #deck-strip > #deck {
    flex: 0 1 auto;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 8px;
  }

  body.phone #deck-strip .deck-actions {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
  }

  /* Inline verbs are their own width, not a share of the screen's. */
  body.phone #deck-strip .deck-actions .button-row button,
  body.phone #deck-strip .deck-actions > button {
    flex: none;
    width: auto;
  }

  body.phone #deck-strip .deck-chips {
    padding: 0;
  }
}
