/* ============================================================
   Cabinet — layout for #login and #lobby
   ============================================================
   Loaded AFTER style.css. It adds layout only: no new palette,
   no new component styling, and nothing outside those two
   screens. Everything it targets is a wrapper class added in
   index.html — no bound id is renamed, moved out of its screen,
   or given a style it did not already have.

   Structure, per screen:

     .panel.cabinet
       .cab-marquee        full width, double rule under it
       .cab-col            one per column, hairline between
       (.cab-col.cab-*)    named so the order can be set per device

   Device switching follows the existing convention: body.pads
   and body.touch, set once at boot by detectDevice(). There is
   ONE width media query in this file and it is scoped to
   body:not(.pads) so it can never apply to a tablet.
   ------------------------------------------------------------ */

:root {
  /* Extensions of the existing palette, not replacements. --line is the
     hairline inside a panel; the cabinet needs a slightly stronger one for
     the frame and the dividers between columns. */
  --rule: rgba(120, 160, 220, 0.35);
  --cab-fill: rgba(6, 10, 20, 0.6);
}

/* ---------- the cabinet itself ---------- */

/*
 * The overlay centres its panel with flexbox, and a centred flex child that
 * grows past its container overflows EQUALLY IN BOTH DIRECTIONS — with the
 * left-hand half permanently unreachable, because you cannot scroll to it.
 * That is what "clipped on the left and unreactive" is, every time.
 *
 * `safe center` centres while there is room and falls back to start-aligned
 * the moment there is not, so nothing is ever put out of reach; `overflow:
 * auto` then makes what is left of the overflow scrollable. Auto margins do
 * the same job in browsers that do not know `safe`, so both are here.
 *
 * Scoped to the two cabinet screens — the small dialogs are never wider than
 * the window and do not need it.
 */
#login.overlay,
#lobby.overlay {
  overflow: auto;
  justify-content: safe center;
  align-items: safe center;
  /*
   * `inset: 0` on a fixed element measures the LARGE viewport on mobile
   * Safari — the one you get once the address bar has scrolled away — so the
   * foot of the panel sits behind the address bar that is actually on screen.
   * On the login screen that is the Launch button. `dvh` is the viewport as
   * it currently is; browsers that do not know the unit drop the line and
   * keep `inset: 0`, which is what they were doing anyway.
   */
  height: 100dvh;
  /*
   * index.html asks for `viewport-fit=cover`, so without this the marquee
   * runs under the notch and the button under the home indicator. Every
   * inset is 0 on hardware that has none, including every desktop.
   */
  padding: env(safe-area-inset-top) env(safe-area-inset-right)
           env(safe-area-inset-bottom) env(safe-area-inset-left);
}

.panel.cabinet {
  /* Overrides .panel's 440/680px column. The cabinet IS the panel: it takes
     the screen and the canvas shows through its fill rather than being
     covered by an opaque card. */
  width: min(1560px, 94vw);
  /*
   * `max-width: none` alone was not the problem, but it was not the answer
   * either: a grid container still cannot shrink below its content's
   * min-content width, so `width: 94vw` was being quietly overruled from the
   * inside. Cap it explicitly, and let it shrink.
   */
  max-width: 94vw;
  min-width: 0;
  margin: auto;
  max-height: 92vh;
  padding: 0;
  overflow: hidden;            /* columns scroll, the frame does not */
  background: var(--cab-fill);
  border: 1px solid var(--rule);
  border-radius: 0;            /* a cabinet has corners */
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.55);
  display: grid;
  /*
   * The row the columns live in MUST be bounded, and this is the line that
   * bounds it.
   *
   * `grid-auto-rows: minmax(0, auto)` sized that row to its tallest column's
   * content. A column was therefore always exactly as tall as what was in it,
   * which means `.cab-col { overflow-y: auto }` never had anything to scroll —
   * an auto-height box cannot overflow itself. The row simply grew past the
   * panel and `overflow: hidden` cropped it, taking the Launch button with it
   * in the two login modes tall enough to reach the bottom.
   *
   * `minmax(0, 1fr)` caps the row at whatever is left after the marquee, so
   * the columns are finally shorter than their content and start scrolling.
   */
  grid-template-rows: auto minmax(0, 1fr);
  grid-auto-rows: minmax(0, auto);
}

/* The marquee. Both screens use it; only the contents differ. */
.cab-marquee {
  grid-column: 1 / -1;
  /*
   * The floor under the whole cabinet's width.
   *
   * Grid items default to `min-width: auto`, so a track can never be narrower
   * than the widest thing in it. `.cab-col` opts out; the marquee did not, and
   * it holds a title with up to 34px of letter-spacing — which gave the panel
   * a min-content width far wider than a small window and pushed it off both
   * edges of the screen.
   */
  min-width: 0;
  padding: 30px 34px 26px;
  text-align: center;
  border-bottom: 3px double var(--rule);
}
.cab-marquee .sub { margin: 14px 0 0; letter-spacing: 5px; text-transform: uppercase; }
/* The floor matters more than the ceiling here: 30px type with 8px of
   tracking is enormous in a 700px window, and it was the clamp minimum rather
   than any deliberate choice that made the marquee refuse to get smaller. */
.panel.cabinet h1 {
  font-size: clamp(18px, 3.4vw, 52px);
  letter-spacing: clamp(2px, 2.4vw, 34px);
  overflow-wrap: anywhere;
}
/* h1 span is `display: block` in style.css — inline keeps the marquee to one
   line where there is room for it. */
.panel.cabinet h1 span { display: inline; }

.cab-col {
  min-width: 0;               /* never let a table's min-content widen a track */
  min-height: 0;
  padding: 30px 32px;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
}
/* Hairline between columns, drawn as a border so no extra elements are
   needed and so it disappears by itself when the columns stack. */
.cab-col + .cab-col { border-left: 1px solid var(--rule); }

.cab-sub {
  font-size: 9px;
  letter-spacing: 2px;
  color: var(--dim);
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 14px;
  text-transform: uppercase;
}
.cab-copy {
  margin: 0 0 24px;
  font-size: 13px;
  line-height: 1.85;
  color: #8f9fbd;
  text-wrap: pretty;
}

/* ============================================================
   #login
   ============================================================ */

#login .panel.cabinet { grid-template-columns: 1fr 1.05fr 1fr; }

/* The board is the front page, so it gets a column of its own and its totals
   sit at the foot of it — the closest thing to a cabinet footer that keeps
   #arcade-totals inside #arcade, which is what main.js hides as one unit. */
#login .cab-board { display: flex; flex-direction: column; }
#login #arcade {
  margin: 0;
  padding: 0;
  border-top: none;
  /* Shrink off, for the same reason as the form: ten score rows plus the
     totals are taller than this column on a short window, and `flex: 1` would
     size the board by the space available rather than by what is in it —
     silently cropping the bottom of the table and the totals with it. */
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
}
#login .arcade-head { font-size: 11px; letter-spacing: 6px; margin-bottom: 16px; }
#login #arcade-top { font-size: 15px; }
#login #arcade-top td { padding: 7px 0; }
#login #arcade-top .who { max-width: none; letter-spacing: 2px; }
#login #arcade-totals { margin-top: auto; }

#login .cab-form { display: flex; flex-direction: column; }
/* The tab strip loses its pill: three flush cells divided by hairlines reads
   as a cabinet selector rather than a segmented control. */
#login .cab-form .tabs {
  margin-bottom: 26px;
  padding: 0;
  gap: 1px;
  background: var(--rule);
  border: none;
  border-radius: 0;
}
#login .cab-form .tab {
  padding: 15px 10px;         /* >=44px tall: this is a tap target on a tablet */
  border-radius: 0;
  background: #080d18;
  letter-spacing: 3px;
  font-size: 11px;
}
#login .cab-form .tab.active { font-weight: 700; }
/**
 * `flex: 1 0 auto`, and the `0` is the whole point.
 *
 * `flex: 1` is `flex: 1 1 0%` — basis nothing, shrink allowed — so the form
 * box was sized by the column rather than by its own content, and quietly
 * shrank below it. The column's scrollHeight therefore never exceeded its
 * height, `overflow-y: auto` had nothing to scroll, and the frame's
 * `overflow: hidden` clipped whatever hung out of the bottom.
 *
 * That was invisible in the Pilot view, where the form is short, and bit in
 * the two modes that add a row: Private rooms (a room list and a password) and
 * Admin (a password). The Launch button was drawn past the fold with no way to
 * reach it — the one control on the screen that has to work.
 *
 * With shrink off the form is at least as tall as its content, the column
 * overflows honestly, and it scrolls. `margin-top: auto` on the button still
 * pins it to the bottom when there IS spare room, and resolves to zero when
 * there is not, so it simply follows the content instead of being stranded.
 */
#login .cab-form #login-form {
  display: flex;
  flex-direction: column;
  flex: 1 0 auto;
}
#login .cab-form label { margin-bottom: 20px; }
#login #login-name { padding: 15px 16px; font-size: 22px; letter-spacing: 5px; }
#login #login-pass { padding: 14px 16px; font-size: 18px; letter-spacing: 4px; }
#login #login-btn {
  margin-top: auto;
  padding: 20px 0;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 10px;
  background: var(--accent);
  border-color: var(--accent);
  color: #04211c;
  border-radius: 0;
}
#login #login-btn:hover { filter: brightness(1.12); }
/* Swatches are <button>s generated by main.js, so they are real tap targets. */
#login #colour-swatches { gap: 7px; }
#login .swatch { width: 44px; height: 44px; border-radius: 0; }

#login .cab-how .controls-hint { margin-top: 0; padding-top: 0; border-top: none; }
#login .cab-how kbd { min-width: 26px; text-align: center; }

/* ============================================================
   #lobby
   ============================================================ */

#lobby .panel.cabinet {
  /* pilots · room · briefing · this match. The briefing gets the elastic
     track because it carries three tables; minmax(0,…) so it cannot be
     floored at min-content and push the last column off the frame. */
  grid-template-columns: 0.85fr 1fr minmax(0, 1.6fr) 0.8fr;
}

#lobby .cab-marquee {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px 40px;
  text-align: left;
  /* Flex items default to min-width: auto too, so a title with 12px of
     tracking beside a 48px countdown set the same immovable floor under the
     panel that the login marquee did. Let them wrap, and let them shrink. */
  flex-wrap: wrap;
}
#lobby .cab-marquee > * { min-width: 0; }
#lobby .cab-marquee h2 {
  margin: 0;
  font-size: clamp(17px, 1.8vw, 30px);
  letter-spacing: clamp(3px, 1vw, 12px);
}
#lobby .cab-marquee .sub { margin: 12px 0 0; letter-spacing: 1.5px; text-transform: none; }
/* The clock moves into the marquee and keeps its own hidden/imminent states. */
#lobby #lobby-clock {
  margin: 0;
  padding: 0;
  border: none;
  gap: 22px;
  flex: 0 0 auto;
}
#lobby #lobby-countdown { font-size: clamp(30px, 5vw, 84px); line-height: 0.9; }

#lobby #lobby-warning { grid-column: 1 / -1; margin: 0; border-radius: 0; border-left: none; border-right: none; }

#lobby .cab-pilots #lobby-roster {
  max-height: none;           /* the column scrolls now, not the roster */
  flex-direction: column;
  flex-wrap: nowrap;
  gap: 8px;
  margin-bottom: 0;
}
#lobby .lobby-pilot { border-radius: 0; padding: 8px 12px; font-size: 13px; }

#lobby .cab-room { display: flex; flex-direction: column; }
#lobby .cab-room #lobby-chat { margin-top: 0; display: flex; flex-direction: column; flex: 1; min-height: 0; }
#lobby #lobby-chat-log {
  height: auto;
  flex: 1;
  min-height: 140px;
  justify-content: flex-end;
  border-radius: 0;
  background: transparent;
  border: none;
  padding: 0;
  font-size: 13px;
  gap: 8px;
}
#lobby #lobby-chat-input { border-radius: 0; padding: 15px 14px; font-size: 13px; }

/* The briefing, all three pages at once. Needs the paintCarousel change in
   hud.js — with the single-page markup this rule is simply a no-op. */
#lobby #carousel { margin-bottom: 0; }
/*
 * Two columns, not three, and the power-ups page gets a row to itself.
 *
 * Three across put it in about 186px: the briefing is 1.6fr of a four-column
 * cabinet, and that gets divided by three again. Its table is three columns
 * wide with a prose Effect in the last one, so 186px bought a few words a row
 * and it was unreadable — which is the one page nobody can skip, since it is
 * where mines, burning and the boss drops are explained.
 *
 * Full width of the briefing instead, roughly 520px, with Controls and Scoring
 * sharing the row above. Those two cope: one is a list of keys, the other a
 * two-column table of numbers, and neither has a sentence in it.
 *
 * Done with `order` and a span rather than explicit rows, deliberately. A
 * spanning item forces its own row under auto-placement, so this arrangement
 * falls out on its own — and in the one-column layouts further down it
 * degrades to a reordering instead of collapsing, which is exactly what
 * pinning `grid-row` would have broken.
 */
#lobby #carousel-panel {
  min-height: 0;
  animation: none;            /* nothing is rotating, so nothing should fade in */
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 26px 30px;
  align-items: start;
}
#lobby .cr-controls { order: 0; }
#lobby .cr-scoring { order: 1; }
#lobby .cr-power-ups { order: 2; grid-column: 1 / -1; }
#lobby .cr-page { min-width: 0; }
#lobby .cr-page h3 { padding-bottom: 12px; border-bottom: 1px solid var(--line); }
#lobby .cr-table { table-layout: fixed; }
#lobby .cr-note { display: none; }   /* the prose belongs to the phone's one page */
#lobby #carousel-dots { display: none; }

#lobby .cab-meta { display: flex; flex-direction: column; }
#lobby .cab-meta .lobby-settings {
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: var(--line);
  margin-bottom: 0;
}
#lobby .cab-meta .lobby-settings div { border: none; border-radius: 0; background: #080d18; }
#lobby .cab-meta .lobby-actions { margin: 18px 0 0; }
#lobby .cab-meta #btn-leave { width: 100%; padding: 14px 0; border-radius: 0; }

/* ============================================================
   Portrait — body.pads (tablet) and body.pads.touch (phone)
   ============================================================
   Both are portrait-first, so the columns stack. The frame, the
   double-rule marquee and the hairline dividers all survive;
   only the direction changes.

   TWO THINGS WERE WRONG HERE AND NEITHER IS VISIBLE IN THE
   SOURCE, SO THEY ARE WRITTEN DOWN.

   1. The column counts never applied. `#login .panel.cabinet`
      carries an id; `body.pads .panel.cabinet` and
      `body.touch .panel.cabinet` do not, and no number of
      classes outweighs one id. So the login screen stayed a
      THREE-column grid on a phone and on a tablet alike, and the
      lobby stayed a four-column one — it escaped only because a
      stale `display: flex` in style.css happened to take grid
      out of the picture altogether. Any override of a
      `grid-template-columns` that was set on `#login`/`#lobby`
      has to name that id too, and they all do now.

   2. The frame cropped rather than scrolled. This section
      inherited the desktop frame — bounded rows plus
      `overflow: hidden` — which only works when every column is
      short enough to fit. The form sat in `minmax(0, 1fr)` and
      took everything left after the marquee; the board and the
      how-it-plays copy were placed in a third row that fell
      outside the frame and was cropped away with nothing to
      scroll. They were not below the fold on a tablet. They were
      not on the page.

   The small-window desktop query at the foot of this file had
   already worked out the answer — one document that scrolls —
   but it is scoped `body:not(.pads)`, so neither touch device
   could ever reach it. It is applied properly here instead.
   ------------------------------------------------------------ */

body.pads .panel.cabinet {
  /* Full bleed. `max-width: 94vw` comes from the desktop rule and would leave
     a 3vw gutter down each side of a screen with none to spare — with the
     side borders already turned off to meet an edge they never reach. */
  width: 100%;
  max-width: 100%;
  max-height: 100%;
  /* style.css sets `body.touch .panel { padding: 16px 18px }` for the small
     dialogs and it outweighs `.panel.cabinet { padding: 0 }`, which floated
     the frame's own inset inside itself: a double-rule marquee stopping short
     of the edges it is drawn to meet. The cabinet's padding is on its
     columns. */
  padding: 0;
  border-left: none;
  border-right: none;
  /* The four lines that make the frame scroll instead of crop. */
  grid-template-rows: none;
  grid-auto-rows: auto;
  overflow-y: auto;
  overscroll-behavior: contain;
}
/* ...and with the frame scrolling, the columns must not, or the outer
   scrollbar has nothing to move and every column becomes a three-line scroll
   box with the control you want at the bottom of it and no sign that it is. */
body.pads .cab-col { overflow: visible; }

/* Two columns on a tablet — and said with the id, or it does not happen. */
body.pads #login .panel.cabinet,
body.pads #lobby .panel.cabinet { grid-template-columns: 1fr 1fr; }

/* Same story for the height. `#lobby .panel { max-height: 92vh; overflow-y:
   auto }` in style.css carries an id and outranks everything above, so the
   lobby frame would be sized against `vh` — the LARGE viewport on a phone —
   while the overlay holding it is sized against the real one. Say it again
   with an id. */
body.pads #login .panel.cabinet,
body.pads #lobby .panel.cabinet {
  max-height: 100%;
  overflow-x: hidden;
  overflow-y: auto;
}

/* ---- tablet only ----
   Everything below places a column in a two-column grid. On a phone each one
   is either a no-op or actively wrong: `grid-row: 3` on both the board and
   the how-it-plays column stacks them in the same cell, one over the other.
   An item with an explicit row is also placed outright, and auto-placement is
   the only thing `order` affects — so these rules silently disabled the
   phone's ordering as well. */
body.pads:not(.touch) .cab-col + .cab-col { border-left: 1px solid var(--rule); }
/* A column that starts a row must not carry a left border. Grid does not
   expose that, so name the two that begin one. */
body.pads:not(.touch) #login .cab-board,
body.pads:not(.touch) #lobby .cab-pilots { border-left: none; }
body.pads:not(.touch) #lobby .cab-brief { grid-column: 1 / -1; border-left: none; border-top: 1px solid var(--rule); }
body.pads:not(.touch) #lobby .cab-meta { grid-column: 1 / -1; border-left: none; border-top: 1px solid var(--rule); }
body.pads:not(.touch) #lobby .cab-meta .lobby-settings { grid-template-columns: repeat(5, 1fr); }
body.pads:not(.touch) #login .cab-form { grid-column: 1 / -1; grid-row: 2; border-left: none; border-bottom: 1px solid var(--rule); }
body.pads:not(.touch) #login .cab-board { grid-row: 3; }
body.pads:not(.touch) #login .cab-how { grid-row: 3; }
/* A tablet paints all three briefing pages at once — hud.js only rotates on
   body.touch — but three power-up tables across a 768px portrait column is
   not reading, it is three columns of two words. Two up, one under. */
body.pads:not(.touch) #lobby #carousel-panel { grid-template-columns: 1fr 1fr; gap: 24px 30px; }

/* ---- tablet and phone ---- */
body.pads #lobby .cab-marquee { flex-direction: column; text-align: center; gap: 14px; }
body.pads #lobby #lobby-clock { justify-content: center; }
/* The desktop lifted the roster's own scroll because the column scrolls
   instead. Here the FRAME scrolls, so without a ceiling forty pilots push the
   chat, the briefing and the way out arbitrarily far down the page. */
body.pads #lobby #lobby-roster { max-height: 168px; overflow-y: auto; }
/* Anything under 16px makes iOS Safari zoom the page in when the field takes
   focus, and there is no gesture that undoes it while the keyboard is up. */
body.pads #login #login-name,
body.pads #login #login-pass,
body.pads #lobby #lobby-chat-input { font-size: 16px; }
/* The form is the one thing on this screen that has to work with a thumb, so
   nothing in it goes under the 44px everybody agrees on. */
body.pads #login #login-btn { padding: 18px 0; letter-spacing: 6px; }
body.pads #lobby #btn-leave { padding: 16px 0; }
/* A row in the room picker is a tap target as much as the button under it,
   and 34px is not one. */
body.pads #login .room { padding: 13px 14px; font-size: 13px; }
body.pads #login .tab { min-height: 44px; }
/* The desktop's 20px between fields is a lot of a phone screen. */
body.pads #login .cab-form label { margin-bottom: 14px; }
/* Four counters on one line is a desktop assumption. Let them fall onto two
   rather than push the column wider than the screen. */
body.pads #login #arcade-totals { flex-wrap: wrap; justify-content: flex-start; gap: 6px 18px; }
/* In the private-rooms and admin modes main.js hides the board, which leaves
   the column that holds it as an empty bordered strip. On a screen this size
   there is no room for one. */
body.pads #login .cab-board:has(#arcade.hidden) { display: none; }

/* ============================================================
   Phone — body.pads.touch
   ============================================================
   One column, in the order the touch build already decided on:
   clock, pilots, room, then the briefing and the settings. That
   ordering is `order`, and it works now only because the
   tablet's explicit row placements above are scoped away from
   it.
   ------------------------------------------------------------ */

body.touch #login .panel.cabinet,
body.touch #lobby .panel.cabinet { grid-template-columns: 1fr; }
body.touch .cab-col { padding: 16px 18px; }
body.touch .cab-col + .cab-col { border-left: none; border-top: 1px solid var(--rule); }
body.touch .cab-marquee { padding: 18px 18px 16px; }
body.touch .panel.cabinet h1 { font-size: 22px; letter-spacing: 9px; }
body.touch .panel.cabinet h1 span { display: block; }
body.touch #lobby .cab-marquee { order: 0; }
body.touch #lobby .cab-pilots { order: 1; }
body.touch #lobby .cab-room { order: 2; }
body.touch #lobby .cab-brief { order: 3; }
body.touch #lobby .cab-meta { order: 4; }
body.touch #login .cab-marquee { order: 0; }
body.touch #login .cab-form { order: 1; }
body.touch #login .cab-board { order: 2; }
body.touch #login .cab-how { order: 3; }
/* The phone keeps the rotation, so the briefing is one page again — and the
   three-across grid the desktop puts on that panel has to come off with it,
   or the single page is laid out in a column a third of the width. */
body.touch #lobby #carousel-panel { display: block; grid-template-columns: none; }
body.touch #lobby #carousel-dots { display: flex; }
body.touch #lobby .cr-note { display: block; }
body.touch #login .swatch { width: 44px; height: 44px; }
body.touch #login #login-name { letter-spacing: 4px; }
body.touch #lobby #lobby-roster { flex-direction: row; flex-wrap: wrap; gap: 5px; }
body.touch #lobby #lobby-chat-log { min-height: 96px; }
/* Three tabs across 320px. It is the tracking that overflows, not the words. */
body.touch #login .cab-form .tabs { margin-bottom: 18px; }
body.touch #login .cab-form .tab { padding: 14px 4px; letter-spacing: 1px; font-size: 10px; }

/* ------------------------------------------------------------
   A phone held sideways
   ------------------------------------------------------------
   Which is most of the time it is on these screens: the rotate
   prompt is scoped to gameplay, so a match ending drops you into
   the lobby still in landscape. 360 pixels of height against 800
   of width is the one shape where one column is worse than two.

   The dividers cannot be `.cab-col + .cab-col` here — that
   follows DOM order and these columns are reordered — so the
   cells that begin a row and the cells that begin a column are
   named instead.
   ------------------------------------------------------------ */
@media (orientation: landscape) and (max-height: 560px) {
  body.touch #login .panel.cabinet,
  body.touch #lobby .panel.cabinet { grid-template-columns: 1fr 1fr; }
  body.touch .cab-col + .cab-col { border-left: none; border-top: none; }
  body.touch #login .cab-board,
  body.touch #lobby .cab-room,
  body.touch #lobby .cab-meta { border-left: 1px solid var(--rule); }
  body.touch #login .cab-how,
  body.touch #lobby .cab-brief,
  body.touch #lobby .cab-meta { border-top: 1px solid var(--rule); }
  body.touch #login .cab-how { grid-column: 1 / -1; }
  /* The marquee is decoration, and there are 360 pixels to spend. */
  body.touch .cab-marquee { padding: 12px 18px 10px; }
  body.touch .panel.cabinet h1 { font-size: 18px; letter-spacing: 6px; }
  body.touch .panel.cabinet h1 span { display: inline; }
  body.touch #lobby .cab-marquee { flex-direction: row; text-align: left; }
  body.touch #lobby #lobby-roster { max-height: 120px; }
}

/* ============================================================
   Small desktop windows
   ============================================================
   The one width query in this file. Scoped to body:not(.pads)
   so it cannot fight the device classes — a tablet never sees
   it, whatever its width.
   ------------------------------------------------------------ */

@media (max-width: 1280px) {
  body:not(.pads) #login .panel.cabinet { grid-template-columns: 1fr 1fr; }
  body:not(.pads) #login .cab-how { grid-column: 1 / -1; border-left: none; border-top: 1px solid var(--rule); }
  body:not(.pads) #lobby .panel.cabinet { grid-template-columns: 1fr minmax(0, 1.4fr); }
  body:not(.pads) #lobby .cab-brief { grid-column: 1 / -1; border-left: none; border-top: 1px solid var(--rule); }
  body:not(.pads) #lobby .cab-meta { grid-column: 1 / -1; border-left: none; border-top: 1px solid var(--rule); }
  body:not(.pads) #lobby .cab-meta .lobby-settings { grid-template-columns: repeat(5, 1fr); }
}

/* ------------------------------------------------------------
   A window that is not maximised
   ------------------------------------------------------------
   Below this the FRAME scrolls instead of each column scrolling
   inside itself.

   Per-column scrolling is right on a big screen: the roster can
   run long without moving the briefing next to it. In a small
   window it is a trap, because every column becomes its own
   little scroll box a few lines tall, and the control you want
   is at the bottom of one of them with no hint that it is there.
   One document that scrolls is what anybody expects of a small
   window, so that is what it does.

   IT DOES NOT BECOME ONE COLUMN HERE, AND THAT IS THE POINT.

   It used to say it did, in a rule that carried no id and was
   therefore overruled by the three-column rule it was written to
   replace — so the line was inert and the layout stayed wide.
   Fixing the specificity made it real, and one column turned out
   to be the wrong answer: the board is 5 scores, 3 records and 4
   counters, roughly 400px of it, and stacking that above the
   form put the Launch button below the fold on the screen whose
   entire job is to get somebody into a game.

   So: two columns, and THE FORM GOES FIRST. Vertical room is
   what a small window is short of, and two columns is how you
   spend width to buy it back. One column waits until 700px,
   where there is no width left to spend.

   Both queries are scoped `body:not(.pads)`, so a tablet keeps
   its own portrait layout no matter how its viewport measures.
   ------------------------------------------------------------ */
@media (max-width: 1000px), (max-height: 620px) {
  /* The column count has to be said with the id, or it does not happen:
     `#login .panel.cabinet` sets three columns, and one id outweighs any
     number of classes. */
  body:not(.pads) #login .panel.cabinet,
  body:not(.pads) #lobby .panel.cabinet { grid-template-columns: 1fr 1fr; }
  body:not(.pads) .panel.cabinet {
    grid-template-rows: none;      /* nothing to cap: the frame scrolls now */
    grid-auto-rows: auto;
    max-height: 94vh;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  /* ...and with the frame scrolling, the columns must not, or the outer
     scrollbar has nothing to move and the inner ones reappear. */
  body:not(.pads) .cab-col {
    overflow: visible;
    padding: 22px 24px;
  }

  /* The form first, then the board, then the copy — the same ranking the
     phone already uses, and for the same reason: somebody arriving here is
     trying to get into a game, and the board is what they read while they
     decide on a name. */
  body:not(.pads) #login .cab-form { order: 0; }
  body:not(.pads) #login .cab-board { order: 1; }
  body:not(.pads) #login .cab-how { order: 2; grid-column: 1 / -1; }
  body:not(.pads) #lobby .cab-brief,
  body:not(.pads) #lobby .cab-meta { grid-column: auto; }

  /* Dividers are drawn per cell, not with `+`. The sibling combinator follows
     DOM order and the login columns are reordered, so it would put the line
     down the left of the column that starts the row and leave none between
     the two that need one. */
  body:not(.pads) .cab-col + .cab-col { border-left: none; border-top: none; }
  body:not(.pads) #login .cab-board,
  body:not(.pads) #lobby .cab-room,
  body:not(.pads) #lobby .cab-meta { border-left: 1px solid var(--rule); }
  body:not(.pads) #login .cab-how,
  body:not(.pads) #lobby .cab-brief,
  body:not(.pads) #lobby .cab-meta { border-top: 1px solid var(--rule); }

  /* The briefing goes back to a stack; three tables side by side in half a
     small window is unreadable, and the pages still all render. */
  body:not(.pads) #lobby #carousel-panel { grid-template-columns: 1fr; gap: 22px 0; }
  /* One column: the span is a no-op and the order is all that survives, which
     is what it was chosen for. */
  body:not(.pads) #lobby .cab-meta .lobby-settings { grid-template-columns: 1fr 1fr; }
  /* The marquee is decoration; it should not eat a small window. */
  body:not(.pads) .cab-marquee { padding: 20px 24px 16px; }
  body:not(.pads) .panel.cabinet h1 { font-size: clamp(22px, 4vw, 34px); letter-spacing: clamp(6px, 2vw, 14px); }
  /* The roster had its own scroll lifted for the big layout; with the frame
     scrolling it needs a ceiling again or forty pilots push everything off
     the bottom. */
  body:not(.pads) #lobby #lobby-roster { max-height: 180px; overflow-y: auto; }

  /* --- the form has to fit ---
     Two columns buys the height back for the Pilot tab. Private rooms adds a
     room list, a hint and a password field on top of it, which is where the
     Launch button went missing, so the form is put on a diet here rather than
     left to spill past the fold. Everything below still clears 44px. */
  body:not(.pads) #room-list { max-height: 120px; }
  body:not(.pads) #login .cab-form .tabs { margin-bottom: 18px; }
  body:not(.pads) #login .cab-form label { margin-bottom: 12px; }
  body:not(.pads) #login #login-name { padding: 12px 14px; font-size: 18px; }
  body:not(.pads) #login #login-pass { padding: 12px 14px; font-size: 16px; }
  body:not(.pads) #login #login-btn { padding: 16px 0; letter-spacing: 8px; }
}

/* ------------------------------------------------------------
   And finally one column
   ------------------------------------------------------------
   Below 700px there is no width left to spend on a second
   column: half of it is 340px, and the board's own table does
   not fit in that. Same order as above — form, board, copy — so
   the button stays the first thing under the marquee.
   ------------------------------------------------------------ */
@media (max-width: 700px) {
  body:not(.pads) #login .panel.cabinet,
  body:not(.pads) #lobby .panel.cabinet { grid-template-columns: 1fr; }
  body:not(.pads) #login .cab-how { grid-column: auto; }
  /* One column: every divider is a rule across the top, except above the
     column that follows the marquee's own double rule. */
  body:not(.pads) #login .cab-board,
  body:not(.pads) #lobby .cab-room,
  body:not(.pads) #lobby .cab-meta { border-left: none; }
  body:not(.pads) #login .cab-board,
  body:not(.pads) #login .cab-how,
  body:not(.pads) #lobby .cab-room,
  body:not(.pads) #lobby .cab-brief,
  body:not(.pads) #lobby .cab-meta { border-top: 1px solid var(--rule); }
  body:not(.pads) #login .cab-form,
  body:not(.pads) #lobby .cab-pilots { border-top: none; }
}

/* ------------------------------------------------------------
   Records, under the high-score table
   ------------------------------------------------------------
   Same vocabulary as the board above it: a rank-ish glyph on the
   left, the label, then who and how many hard right. Four rows
   of one line each, so it reads as part of the same table rather
   than as a second widget bolted underneath.
   ------------------------------------------------------------ */
#login #arcade-records { margin-top: 22px; }
#login #arcade-records .arcade-head {
  margin-bottom: 10px;
  padding-top: 16px;
  border-top: 1px solid var(--rule);
}
#login .rec {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr) minmax(0, auto) minmax(0, auto);
  align-items: baseline;
  gap: 0 10px;
  padding: 6px 0;
  font-size: 12px;
}
#login .rec .rg { font-size: 13px; line-height: 1; }
#login .rec .rl {
  color: var(--dim);
  letter-spacing: 2px;
  font-size: 10px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-transform: uppercase;
  min-width: 0;
}
#login .rec .rw {
  color: var(--ink);
  text-transform: uppercase;
  letter-spacing: 1px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 96px;
}
#login .rec .rv { color: #ffe066; font-weight: 700; text-align: right; }

/* The board column carries three blocks — five scores, three records, four
   counters — so nothing in it may grow without bound. The score table is
   capped at five rows by main.js for exactly that reason. */
#login .cab-board { min-height: 0; }
